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; } |