Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 2x 2x 2x 2x 2x 2x 2x 2x | import { bytesToHex, concatByteArrays, hexToBytes } from 'micro-stacks/common';
import { entropyToMnemonic, validateMnemonic } from '@scure/bip39';
import { wordlist } from '@scure/bip39/wordlists/english';
// micro-stacks crypto
import { aes128CbcDecrypt } from 'micro-stacks/crypto-aes';
import { hashSha256 } from 'micro-stacks/crypto-sha';
import { hmacSha256 } from 'micro-stacks/crypto-hmac-sha';
import { createPbkdf2 } from 'micro-stacks/crypto-pbkdf2';
/**
* Decrypt an encrypted mnemonic phrase with a password.
* @param encryptedMnemonic - Uint8Array or hex-encoded string of the encrypted mnemonic
* @param password - Password for data
* @return the raw mnemonic phrase
* @private
* @ignore
*/
export async function decryptMnemonic(
encryptedMnemonic: Uint8Array | string,
password: string
): Promise<string> {
const dataBuffer =
typeof encryptedMnemonic === 'string' ? hexToBytes(encryptedMnemonic) : encryptedMnemonic;
const salt = dataBuffer.slice(0, 16);
const hmacSig = dataBuffer.slice(16, 48); // 32 bytes
const cipherText = dataBuffer.slice(48);
const hmacPayload = concatByteArrays([salt, cipherText]);
const pbkdf2 = await createPbkdf2();
const keysAndIV = await pbkdf2.derive(password, salt, 100000, 48, 'sha512');
const encKey = keysAndIV.slice(0, 16);
const macKey = keysAndIV.slice(16, 32);
const iv = keysAndIV.slice(32, 48);
const decryptedResult = await aes128CbcDecrypt(iv, encKey, cipherText);
const hmacDigest = hmacSha256(macKey, hmacPayload);
const hmacSigHash = hashSha256(hmacSig);
const hmacDigestHash = hashSha256(hmacDigest);
Iif (bytesToHex(hmacSigHash) !== bytesToHex(hmacDigestHash))
throw new Error('Wrong password (HMAC mismatch)');
let mnemonic: string;
try {
mnemonic = entropyToMnemonic(decryptedResult, wordlist);
} catch (error) {
console.error('Error thrown by `entropyToMnemonic`');
console.error(error);
throw new Error('Wrong password (invalid plaintext)');
}
Iif (!validateMnemonic(mnemonic, wordlist)) {
throw new Error('Wrong password (invalid plaintext)');
}
return mnemonic;
}
|