1- import * as bip39 from 'bip39' ;
2- import * as crypto from 'crypto' ;
1+ import { promisify } from 'util' ;
2+ import { validateMnemonic , mnemonicToEntropy , entropyToMnemonic } from 'bip39' ;
3+ import { pbkdf2 , randomBytes , createCipheriv , createHmac , createDecipheriv , createHash } from 'crypto' ;
4+
5+ const asyncPbkdf2 = promisify ( pbkdf2 ) ;
36
47/**
58 * Encrypt a mnemonic using password
@@ -8,25 +11,25 @@ import * as crypto from 'crypto';
811 * @returns {Promise<String> } hex-encoded string of the encrypted mnemonic
912 */
1013export async function encryptMnemonic ( phrase , password ) {
11- if ( ! bip39 . validateMnemonic ( phrase ) ) {
14+ if ( ! validateMnemonic ( phrase ) ) {
1215 throw new Error ( 'Not a valid bip39 mnemonic' ) ;
1316 }
1417
15- const plaintextBuffer = Buffer . from ( bip39 . mnemonicToEntropy ( phrase ) , 'hex' ) ;
18+ const plaintextBuffer = Buffer . from ( mnemonicToEntropy ( phrase ) , 'hex' ) ;
1619
1720 // AES-128-CBC with SHA256 HMAC
18- const salt = crypto . randomBytes ( 16 ) ;
19- const keysAndIV = crypto . pbkdf2Sync ( password , salt , 100000 , 48 , 'sha512' ) ;
21+ const salt = randomBytes ( 16 ) ;
22+ const keysAndIV = await asyncPbkdf2 ( password , salt , 100000 , 48 , 'sha512' ) ;
2023 const encKey = keysAndIV . slice ( 0 , 16 ) ;
2124 const macKey = keysAndIV . slice ( 16 , 32 ) ;
2225 const iv = keysAndIV . slice ( 32 , 48 ) ;
2326
24- const cipher = crypto . createCipheriv ( 'aes-128-cbc' , encKey , iv ) ;
27+ const cipher = createCipheriv ( 'aes-128-cbc' , encKey , iv ) ;
2528
2629 const cipherText = Buffer . concat ( [ cipher . update ( plaintextBuffer ) , cipher . final ( ) ] ) ;
2730
2831 const hmacPayload = Buffer . concat ( [ salt , cipherText ] ) ;
29- const hmac = crypto . createHmac ( 'sha256' , macKey ) ;
32+ const hmac = createHmac ( 'sha256' , macKey ) ;
3033 hmac . write ( hmacPayload ) ;
3134 const hmacDigest = hmac . digest ( ) ;
3235 const payload = Buffer . concat ( [ salt , hmacDigest , cipherText ] ) ;
@@ -49,37 +52,29 @@ export async function decryptMnemonic(encryptedMnemonic, password) {
4952 const cipherText = dataBuffer . slice ( 48 ) ;
5053
5154 const hmacPayload = Buffer . concat ( [ salt , cipherText ] ) ;
52- const keysAndIV = crypto . pbkdf2Sync ( password , salt , 100000 , 48 , 'sha512' ) ;
55+ const keysAndIV = await asyncPbkdf2 ( password , salt , 100000 , 48 , 'sha512' ) ;
5356 const encKey = keysAndIV . slice ( 0 , 16 ) ;
5457 const macKey = keysAndIV . slice ( 16 , 32 ) ;
5558 const iv = keysAndIV . slice ( 32 , 48 ) ;
5659
57- const decipher = crypto . createDecipheriv ( 'aes-128-cbc' , encKey , iv ) ;
60+ const decipher = createDecipheriv ( 'aes-128-cbc' , encKey , iv ) ;
5861 const plaintextBuffer = Buffer . concat ( [ decipher . update ( cipherText ) , decipher . final ( ) ] ) ;
5962
6063 const hmac = crypto . createHmac ( 'sha256' , macKey ) ;
6164 hmac . write ( hmacPayload ) ;
6265
6366 const hmacDigest = hmac . digest ( ) ;
64- const hmacSigHash = crypto
65- . createHash ( 'sha256' )
66- . update ( hmacSig )
67- . digest ( )
68- . toString ( 'hex' ) ;
69-
70- const hmacDigestHash = crypto
71- . createHash ( 'sha256' )
72- . update ( hmacDigest )
73- . digest ( )
74- . toString ( 'hex' ) ;
67+ const hmacSigHash = createHash ( 'sha256' ) . update ( hmacSig ) . digest ( ) . toString ( 'hex' ) ;
68+
69+ const hmacDigestHash = createHash ( 'sha256' ) . update ( hmacDigest ) . digest ( ) . toString ( 'hex' ) ;
7570
7671 if ( hmacSigHash !== hmacDigestHash ) {
7772 throw new Error ( 'Wrong password (HMAC mismatch)' ) ;
7873 }
7974
80- const mnemonic = bip39 . entropyToMnemonic ( plaintextBuffer ) ;
75+ const mnemonic = entropyToMnemonic ( plaintextBuffer ) ;
8176
82- if ( ! bip39 . validateMnemonic ( mnemonic ) ) {
77+ if ( ! validateMnemonic ( mnemonic ) ) {
8378 throw new Error ( 'Wrong password (invalid plaintext)' ) ;
8479 }
8580
0 commit comments