import { sha256 , pbkdf2Sync } from "@node-lightning/crypto" ; import { EnglishWordList } from "./MnemonicWordLists" ; import { BitcoinError } from "./BitcoinError" ; import { BitcoinErrorCode } from "./BitcoinErrorCode" ; /**
 * Implements mnemonic seed generation methods as specified in BIP39.
 * https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
 */ export class Mnemonic { /**
     * Default English word list of 2048 words as specified in BIP39
     */ public static English = EnglishWordList ; remarks param phrase param password returns public static phraseToSeed ( phrase , password ? ) { const key = Buffer . from ( phrase . normalize ( "NFKD" ) , "utf-8" ) ; const salt = Buffer . from ( ( "mnemonic" + ( password || "" ) ) . normalize ( "NFKD" ) , "utf-8" ) ; return pbkdf2Sync ( key , salt , 2048 , 64 , "sha512" ) ; } remarks param entropy param wordlist throw BitcoinError throws if the entropy is not between
     * 128 and 256 bits and is not divisible by 32. Throws if the word
     * list is not 2048 words.
     *
     *  returns public static entropyToPhrase ( entropy , wordlist = Mnemonic . English ) { if ( wordlist . length !== 2048 ) { throw new BitcoinError ( BitcoinErrorCode . InvalidMnemonicWordList , { expected : 2048 , got : wordlist . length , } ) ; } if ( entropy . length % 4 > 0 || entropy . length < 16 || entropy . length > 32 ) { throw new BitcoinError ( BitcoinErrorCode . InvalidMnemonicEntropy , { entropy } ) ; } const input = Array . from ( entropy ) ; input . push ( sha256 ( entropy ) [ 0 ] ) ; const [ indices ] = convert ( input , 8 , 11 ) ; const words = indices . map ( i => wordlist [ i ] ) ; return words . join ( " " ) ; } param phrase param wordlist throw BitcoinError throws if word list does not have 2048
     * words. Throws if there is a word that does not below. Throws if
     * the checksum fails.
     *  returns public static phraseToEntropy ( phrase , wordlist = Mnemonic . English ) { if ( wordlist . length !== 2048 ) { throw new BitcoinError ( BitcoinErrorCode . InvalidMnemonicWordList , { expected : 2048 , got : wordlist . length , } ) ; } const words = phrase . split ( " " ) ; const indices = [ ] ; for ( const word of words ) { const index = wordlist . findIndex ( p => p === word ) ; if ( index === - 1 ) { throw new BitcoinError ( BitcoinErrorCode . InvalidMnemonicWord , { word , phrase } ) ; } indices . push ( index ) ; } const results = convert ( indices , 11 , 8 ) ; let checksum = results [ 1 ] ; if ( checksum === null ) { checksum = results [ 0 ] . pop ( ) ; } const entropy = Buffer . from ( results [ 0 ] ) ; const calcedChecksumBits = entropy . length / 4 ; const calcedChecksum = sha256 ( entropy ) [ 0 ] >> ( 8 - calcedChecksumBits ) ; if ( calcedChecksum !== checksum ) { throw new BitcoinError ( BitcoinErrorCode . InvalidMnemonicChecksum , { expected : checksum , got : calcedChecksum , phrase , } ) ; } return entropy ; } } param inWords param inSize param outSize returns function convert ( inWords , inSize , outSize ) { const outWords = [ ] ; const outMask = ( 1 << outSize ) - 1 ; let bufBits = 0 ; let buf = 0 ; for ( const inWord of inWords ) { buf = ( buf << inSize ) | inWord ; bufBits += inSize ; while ( bufBits >= outSize ) { bufBits -= outSize ; outWords . push ( ( buf >> bufBits ) & outMask ) ; } } const remainder = bufBits ? buf & ( ( 1 << bufBits ) - 1 ) : null ; return [ outWords , remainder ] ; }