From bb104ae50c9732584a3646daaa1f61c76b4143bd Mon Sep 17 00:00:00 2001 From: morizon Date: Fri, 3 Jan 2025 11:50:31 +0800 Subject: [PATCH] Fix/secret encrypt async (#6407) * fix: secret async encrypt * fix: secret unit tests --- jest-setup.js | 1 + jest.config.js | 2 +- packages/core/@tests/coreTestsUtils.ts | 4 +- packages/core/src/base/CoreChainApiBase.ts | 10 +- .../core/src/chains/ada/CoreChainSoftware.ts | 7 +- .../core/src/chains/btc/CoreChainSoftware.ts | 18 +- .../core/src/chains/dot/CoreChainSoftware.ts | 17 +- .../chains/lightning/sdkLightning/account.ts | 2 +- .../secret/__tests__/secret-aes256.test.ts | 49 +- .../core/src/secret/__tests__/secret.test.ts | 518 +++++++++++------- packages/core/src/secret/bip32.ts | 2 +- .../encryptors/__tests__/aes256.test.ts | 136 +++++ packages/core/src/secret/encryptors/aes256.ts | 109 +++- packages/core/src/secret/index.test.ts | 86 +-- packages/core/src/secret/index.ts | 154 +++--- packages/kit-bg/src/dbs/local/LocalDbBase.ts | 25 +- .../src/dbs/local/realm/RealmDBAgent.ts | 9 +- .../v4ToV5Migration/V4MigrationForAccount.ts | 4 +- .../v4ToV5Migration/v4local/V4LocalDbBase.ts | 22 +- .../services/ServiceAccount/ServiceAccount.ts | 6 +- .../kit-bg/src/services/ServiceAddressBook.ts | 2 +- .../src/services/ServiceCloudBackup/index.ts | 55 +- .../ServicePassword/biologyAuthUtils.ts | 4 +- .../src/services/ServicePassword/index.ts | 6 +- packages/kit-bg/src/vaults/base/VaultBase.ts | 2 +- packages/kit-bg/src/vaults/impls/ada/Vault.ts | 4 +- .../kit-bg/src/vaults/impls/algo/Vault.ts | 4 +- packages/kit-bg/src/vaults/impls/btc/Vault.ts | 4 +- packages/kit-bg/src/vaults/impls/fil/Vault.ts | 4 +- .../kit-bg/src/vaults/impls/kaspa/Vault.ts | 6 +- .../kit-bg/src/vaults/impls/near/Vault.ts | 4 +- packages/kit-bg/src/vaults/impls/sol/Vault.ts | 2 +- packages/kit-bg/src/vaults/impls/xrp/Vault.ts | 4 +- 33 files changed, 856 insertions(+), 426 deletions(-) create mode 100644 packages/core/src/secret/encryptors/__tests__/aes256.test.ts diff --git a/jest-setup.js b/jest-setup.js index 346df6bdaa4..c8cfc2fc5f0 100644 --- a/jest-setup.js +++ b/jest-setup.js @@ -1,3 +1,4 @@ +/* eslint-disable no-undef */ // require('react-native-reanimated').setUpTests(); // FIX: ReferenceError: self is not defined diff --git a/jest.config.js b/jest.config.js index 1d9ca85b4ae..c87c8057d12 100644 --- a/jest.config.js +++ b/jest.config.js @@ -59,7 +59,7 @@ module.exports = async () => { [ './node_modules/jest-html-reporter', { - 'pageTitle': 'Test Report', + 'pageTitle': 'Jest UnitTest Report', }, ], ], diff --git a/packages/core/@tests/coreTestsUtils.ts b/packages/core/@tests/coreTestsUtils.ts index a18bd0d978f..3b902ab26a9 100644 --- a/packages/core/@tests/coreTestsUtils.ts +++ b/packages/core/@tests/coreTestsUtils.ts @@ -216,7 +216,7 @@ async function expectSignTransactionOk({ const resultImported = await coreApi.signTransaction({ ...signTxPayload, credentials: { - imported: encryptImportedCredential({ + imported: await encryptImportedCredential({ password, credential: { privateKey: account.xpvtRaw || account.privateKeyRaw }, }), @@ -258,7 +258,7 @@ async function expectSignMessageOk({ const resultImported = await coreApi.signMessage({ ...signMsgPayload, credentials: { - imported: encryptImportedCredential({ + imported: await encryptImportedCredential({ password, credential: { privateKey: account.privateKeyRaw }, }), diff --git a/packages/core/src/base/CoreChainApiBase.ts b/packages/core/src/base/CoreChainApiBase.ts index d01081aa0c1..e2cbd2e5fd3 100644 --- a/packages/core/src/base/CoreChainApiBase.ts +++ b/packages/core/src/base/CoreChainApiBase.ts @@ -20,7 +20,7 @@ import { decrypt, decryptImportedCredential, ed25519, - encrypt, + encryptAsync, nistp256, secp256k1, } from '../secret'; @@ -140,7 +140,9 @@ export abstract class CoreChainApiBase { password, credential: credentials.imported, }); - const encryptPrivateKey = bufferUtils.bytesToHex(encrypt(password, p)); + const encryptPrivateKey = bufferUtils.bytesToHex( + await encryptAsync({ password, data: p }), + ); privateKeys[account.path] = encryptPrivateKey; privateKeys[''] = encryptPrivateKey; } @@ -170,7 +172,7 @@ export abstract class CoreChainApiBase { ); } - const keys = batchGetPrivateKeys( + const keys = await batchGetPrivateKeys( curve, hdCredential, password, @@ -205,7 +207,7 @@ export abstract class CoreChainApiBase { let pvtkeyInfos: ISecretPrivateKeyInfo[] = []; if (isPrivateKeyMode) { - pvtkeyInfos = batchGetPrivateKeys( + pvtkeyInfos = await batchGetPrivateKeys( curve, hdCredential, password, diff --git a/packages/core/src/chains/ada/CoreChainSoftware.ts b/packages/core/src/chains/ada/CoreChainSoftware.ts index d284ebcac54..d7f4db288b8 100644 --- a/packages/core/src/chains/ada/CoreChainSoftware.ts +++ b/packages/core/src/chains/ada/CoreChainSoftware.ts @@ -2,7 +2,7 @@ import { checkIsDefined } from '@onekeyhq/shared/src/utils/assertUtils'; import bufferUtils from '@onekeyhq/shared/src/utils/bufferUtils'; import { CoreChainApiBase } from '../../base/CoreChainApiBase'; -import { decrypt, encrypt } from '../../secret'; +import { decrypt, encryptAsync } from '../../secret'; import { ECoreApiExportedSecretKeyType, type ICoreApiGetAddressItem, @@ -53,7 +53,10 @@ export default class CoreChainSoftware extends CoreChainApiBase { const xprv = await generateExportedCredential(password, hdCredential, path); const privateKey = decodePrivateKeyByXprv(xprv); - const privateKeyEncrypt = encrypt(password, privateKey); + const privateKeyEncrypt = await encryptAsync({ + password, + data: privateKey, + }); const map: ICoreApiPrivateKeysMap = { [path]: bufferUtils.bytesToHex(privateKeyEncrypt), diff --git a/packages/core/src/chains/btc/CoreChainSoftware.ts b/packages/core/src/chains/btc/CoreChainSoftware.ts index 1cfa6cfe05d..4bba9e79345 100644 --- a/packages/core/src/chains/btc/CoreChainSoftware.ts +++ b/packages/core/src/chains/btc/CoreChainSoftware.ts @@ -30,7 +30,7 @@ import { BaseBip32KeyDeriver, batchGetPublicKeysAsync, decrypt, - encrypt, + encryptAsync, mnemonicFromEntropyAsync, mnemonicToSeedAsync, secp256k1, @@ -433,7 +433,7 @@ export default class CoreChainSoftwareBtc extends CoreChainApiBase { return psbt; } - private appendImportedRelPathPrivateKeys({ + private async appendImportedRelPathPrivateKeys({ privateKeys, password, relPaths, @@ -441,7 +441,7 @@ export default class CoreChainSoftwareBtc extends CoreChainApiBase { privateKeys: ICoreApiPrivateKeysMap; password: string; relPaths?: string[]; - }): ICoreApiPrivateKeysMap { + }): Promise { const deriver = new BaseBip32KeyDeriver( Buffer.from('Bitcoin seed'), secp256k1, @@ -457,12 +457,12 @@ export default class CoreChainSoftwareBtc extends CoreChainApiBase { const cache: Record = {}; - relPaths?.forEach((relPath) => { + for (const relPath of relPaths ?? []) { const pathComponents = relPath.split('/'); let currentPath = ''; let parent = startKey; - pathComponents.forEach((pathComponent) => { + for (const pathComponent of pathComponents) { currentPath = currentPath.length > 0 ? `${currentPath}/${pathComponent}` @@ -475,13 +475,13 @@ export default class CoreChainSoftwareBtc extends CoreChainApiBase { cache[currentPath] = thisPrivKey; } parent = cache[currentPath]; - }); + } // TODO use dbAccountAddresses save fullPath/relPath key privateKeys[relPath] = bufferUtils.bytesToHex( - encrypt(password, cache[relPath].key), + await encryptAsync({ password, data: cache[relPath].key }), ); - }); + } return privateKeys; } @@ -703,7 +703,7 @@ export default class CoreChainSoftwareBtc extends CoreChainApiBase { curve: curveName, }); if (isImported) { - this.appendImportedRelPathPrivateKeys({ + await this.appendImportedRelPathPrivateKeys({ privateKeys, password, relPaths, diff --git a/packages/core/src/chains/dot/CoreChainSoftware.ts b/packages/core/src/chains/dot/CoreChainSoftware.ts index f62e6549b1d..d1022a6bd10 100644 --- a/packages/core/src/chains/dot/CoreChainSoftware.ts +++ b/packages/core/src/chains/dot/CoreChainSoftware.ts @@ -13,10 +13,11 @@ import { CoreChainApiBase } from '../../base/CoreChainApiBase'; import { decrypt, decryptImportedCredential, - encrypt, + encryptAsync, mnemonicFromEntropy, } from '../../secret'; import { + ECoreApiExportedSecretKeyType, type ICoreApiGetAddressItem, type ICoreApiGetAddressQueryImported, type ICoreApiGetAddressQueryPublicKey, @@ -30,7 +31,6 @@ import { type ICurveName, type ISignedTxPro, } from '../../types'; -import { ECoreApiExportedSecretKeyType } from '../../types'; import { slicePathTemplate } from '../../utils'; import { serializeMessage, serializeSignedTransaction } from './sdkDot'; @@ -95,16 +95,21 @@ export default class CoreChainSoftware extends CoreChainApiBase { const usedRelativePaths = relPaths || [pathComponents.pop() as string]; const basePath = pathComponents.join('/'); const mnemonic = mnemonicFromEntropy(credentials.hd, password); - const keys = usedRelativePaths.map((relPath) => { + const keysPromised = usedRelativePaths.map(async (relPath) => { const path = `${basePath}/${relPath}`; const keyPair = derivationHdLedger(mnemonic, path); return { path, - key: encrypt(password, Buffer.from(keyPair.secretKey.slice(0, 32))), + key: await encryptAsync({ + password, + data: Buffer.from(keyPair.secretKey.slice(0, 32)), + }), }; }); + const keys = await Promise.all(keysPromised); + privateKeys = keys.reduce( (ret, key) => ({ ...ret, [key.path]: bufferUtils.bytesToHex(key.key) }), {}, @@ -115,7 +120,9 @@ export default class CoreChainSoftware extends CoreChainApiBase { password, credential: credentials.imported, }); - const encryptPrivateKey = bufferUtils.bytesToHex(encrypt(password, p)); + const encryptPrivateKey = bufferUtils.bytesToHex( + await encryptAsync({ password, data: p }), + ); privateKeys[account.path] = encryptPrivateKey; privateKeys[''] = encryptPrivateKey; } diff --git a/packages/core/src/chains/lightning/sdkLightning/account.ts b/packages/core/src/chains/lightning/sdkLightning/account.ts index 98e9c38f583..162e88c21a2 100644 --- a/packages/core/src/chains/lightning/sdkLightning/account.ts +++ b/packages/core/src/chains/lightning/sdkLightning/account.ts @@ -30,7 +30,7 @@ export const generateNativeSegwitAccounts = async ({ (index) => `${index.toString()}'`, // btc ); - const pubkeyInfos = batchGetPublicKeys( + const pubkeyInfos = await batchGetPublicKeys( curve, hdCredential, password, diff --git a/packages/core/src/secret/__tests__/secret-aes256.test.ts b/packages/core/src/secret/__tests__/secret-aes256.test.ts index 1b2bc0c5510..525e4e76735 100644 --- a/packages/core/src/secret/__tests__/secret-aes256.test.ts +++ b/packages/core/src/secret/__tests__/secret-aes256.test.ts @@ -85,11 +85,12 @@ describe('AES256 Encryption Tests', () => { expect(decrypted.toString()).toBe(TEST_DATA); }); - it('should throw on incorrect password', () => { + it('should throw on incorrect password', async () => { const encrypted = encrypt(TEST_PASSWORD, TEST_DATA_HEX); - expect(() => - decrypt(encodePassword({ password: 'wrong-password' }), encrypted), - ).toThrow(); + const encodedPassword = await encodePassword({ + password: 'wrong-password', + }); + expect(() => decrypt(encodedPassword, encrypted)).toThrow(); }); it('should throw on empty password', () => { @@ -214,8 +215,8 @@ describe('AES256 Encryption Tests', () => { }); describe('encodePassword/decodePassword', () => { - it('should encode and decode password with snapshot', () => { - const encoded = encodePassword({ + it('should encode and decode password with snapshot', async () => { + const encoded = await encodePassword({ password: TEST_PASSWORD, key: 'test-key', }); @@ -228,8 +229,8 @@ describe('AES256 Encryption Tests', () => { expect(decoded).toBe(TEST_PASSWORD); }); - it('should throw on incorrect key', () => { - const encoded = encodePassword({ + it('should throw on incorrect key', async () => { + const encoded = await encodePassword({ password: TEST_PASSWORD, key: 'test-key', }); @@ -242,15 +243,15 @@ describe('AES256 Encryption Tests', () => { }); // TODO empty key should throw - it.skip('should throw on empty key', () => { - expect(() => + it.skip('should throw on empty key', async () => { + await expect( encodePassword({ password: TEST_PASSWORD, key: '', }), - ).toThrow(); + ).rejects.toThrow(); - const encoded = encodePassword({ + const encoded = await encodePassword({ password: TEST_PASSWORD, key: 'test-key', }); @@ -264,8 +265,8 @@ describe('AES256 Encryption Tests', () => { }); describe('encodeSensitiveText/decodeSensitiveText', () => { - it('should encode and decode sensitive text with snapshot', () => { - const encoded = encodeSensitiveText({ + it('should encode and decode sensitive text with snapshot', async () => { + const encoded = await encodeSensitiveText({ text: TEST_DATA, key: 'test-key', }); @@ -278,8 +279,8 @@ describe('AES256 Encryption Tests', () => { expect(decoded).toBe(TEST_DATA); }); - it('should throw on incorrect key', () => { - const encoded = encodeSensitiveText({ + it('should throw on incorrect key', async () => { + const encoded = await encodeSensitiveText({ text: TEST_DATA, key: 'test-key', }); @@ -292,7 +293,7 @@ describe('AES256 Encryption Tests', () => { }); // TODO empty key should throw - it.skip('should throw on empty key', () => { + it.skip('should throw on empty key', async () => { expect(() => encodeSensitiveText({ text: TEST_DATA, @@ -300,7 +301,7 @@ describe('AES256 Encryption Tests', () => { }), ).toThrow(); - const encoded = encodeSensitiveText({ + const encoded = await encodeSensitiveText({ text: TEST_DATA, key: 'test-key', }); @@ -375,8 +376,8 @@ describe('AES256 Encryption Tests', () => { }); describe('isEncodedSensitiveText and ensureSensitiveTextEncoded', () => { - it('should correctly identify encoded sensitive text', () => { - const encoded = encodeSensitiveText({ + it('should correctly identify encoded sensitive text', async () => { + const encoded = await encodeSensitiveText({ text: TEST_DATA, key: 'test-key', }); @@ -384,8 +385,8 @@ describe('AES256 Encryption Tests', () => { expect(isEncodedSensitiveText('not-encoded-text')).toBe(false); }); - it('should handle both aes and xor prefixes', () => { - const aesEncoded = encodeSensitiveText({ + it('should handle both aes and xor prefixes', async () => { + const aesEncoded = await encodeSensitiveText({ text: TEST_DATA, key: 'test-key', }); @@ -404,8 +405,8 @@ describe('AES256 Encryption Tests', () => { ); }); - it('should not throw for valid encoded text in ensureSensitiveTextEncoded', () => { - const encoded = encodeSensitiveText({ + it('should not throw for valid encoded text in ensureSensitiveTextEncoded', async () => { + const encoded = await encodeSensitiveText({ text: TEST_DATA, key: 'test-key', }); diff --git a/packages/core/src/secret/__tests__/secret.test.ts b/packages/core/src/secret/__tests__/secret.test.ts index 6734a15326c..7ddaea42635 100644 --- a/packages/core/src/secret/__tests__/secret.test.ts +++ b/packages/core/src/secret/__tests__/secret.test.ts @@ -93,13 +93,18 @@ describe('Secret Module Tests', () => { ), }; - it('should derive normal child key for secp256k1', () => { + it('should derive normal child key for secp256k1', async () => { const encryptedParent = { key: encrypt(testPassword, testMasterKey.key), chainCode: testMasterKey.chainCode, }; - const childKey = CKDPriv('secp256k1', encryptedParent, 0, testPassword); + const childKey = await CKDPriv( + 'secp256k1', + encryptedParent, + 0, + testPassword, + ); // Decrypt and verify the derived key const decryptedKey = decrypt(testPassword, childKey.key); @@ -115,14 +120,14 @@ describe('Secret Module Tests', () => { expect(publicKey.length).toBeGreaterThan(0); }); - it('should derive hardened child key for secp256k1', () => { + it('should derive hardened child key for secp256k1', async () => { const encryptedParent = { key: encrypt(testPassword, testMasterKey.key), chainCode: testMasterKey.chainCode, }; const hardenedIndex = 0x80_00_00_00; // 2^31 - const childKey = CKDPriv( + const childKey = await CKDPriv( 'secp256k1', encryptedParent, hardenedIndex, @@ -134,20 +139,20 @@ describe('Secret Module Tests', () => { expect(childKey.chainCode.length).toBe(32); }); - it('should only support hardened derivation for ed25519', () => { + it('should only support hardened derivation for ed25519', async () => { const encryptedParent = { key: encrypt(testPassword, testMasterKey.key), chainCode: testMasterKey.chainCode, }; // Normal index should throw - expect(() => { - CKDPriv('ed25519', encryptedParent, 0, testPassword); - }).toThrow('Only hardened CKDPriv is supported for ed25519'); + await expect( + CKDPriv('ed25519', encryptedParent, 0, testPassword), + ).rejects.toThrow('Only hardened CKDPriv is supported for ed25519'); // Hardened index should work const hardenedIndex = 0x80_00_00_00; - const childKey = CKDPriv( + const childKey = await CKDPriv( 'ed25519', encryptedParent, hardenedIndex, @@ -157,32 +162,37 @@ describe('Secret Module Tests', () => { expect(childKey.chainCode.length).toBe(32); }); - it('should throw error for invalid index', () => { + it('should throw error for invalid index', async () => { const encryptedParent = { key: encrypt(testPassword, testMasterKey.key), chainCode: testMasterKey.chainCode, }; - expect(() => { - CKDPriv('secp256k1', encryptedParent, -1, testPassword); - }).toThrow('Overflowed.'); + await expect( + CKDPriv('secp256k1', encryptedParent, -1, testPassword), + ).rejects.toThrow('Invalid index.'); - expect(() => { - CKDPriv('secp256k1', encryptedParent, 2 ** 32, testPassword); - }).toThrow('Overflowed.'); + await expect( + CKDPriv('secp256k1', encryptedParent, 2 ** 32, testPassword), + ).rejects.toThrow('Overflowed.'); - expect(() => { - CKDPriv('secp256k1', encryptedParent, 1.5, testPassword); - }).toThrow('Invalid index'); + await expect( + CKDPriv('secp256k1', encryptedParent, 1.5, testPassword), + ).rejects.toThrow('Invalid index'); }); - it('should derive child key for nistp256', () => { + it('should derive child key for nistp256', async () => { const encryptedParent = { key: encrypt(testPassword, testMasterKey.key), chainCode: testMasterKey.chainCode, }; - const childKey = CKDPriv('nistp256', encryptedParent, 0, testPassword); + const childKey = await CKDPriv( + 'nistp256', + encryptedParent, + 0, + testPassword, + ); const decryptedKey = decrypt(testPassword, childKey.key); expect(decryptedKey.length).toBe(32); @@ -192,24 +202,29 @@ describe('Secret Module Tests', () => { expect(childKey.chainCode).not.toEqual(testMasterKey.chainCode); // Verify we can derive multiple children - const secondChild = CKDPriv('nistp256', childKey, 1, testPassword); + const secondChild = await CKDPriv('nistp256', childKey, 1, testPassword); expect(secondChild.key.length).toBeGreaterThan(0); expect(secondChild.chainCode.length).toBe(32); }); - it('should match snapshot for secp256k1', () => { + it('should match snapshot for secp256k1', async () => { const encryptedParent = { key: encrypt(testPassword, testMasterKey.key), chainCode: testMasterKey.chainCode, }; - const childKey = CKDPriv('secp256k1', encryptedParent, 0, testPassword); + const childKey = await CKDPriv( + 'secp256k1', + encryptedParent, + 0, + testPassword, + ); expect({ key: childKey.key.toString('hex'), chainCode: childKey.chainCode.toString('hex'), }).toMatchSnapshot('secp256k1-child-key'); - const hardenedChildKey = CKDPriv( + const hardenedChildKey = await CKDPriv( 'secp256k1', encryptedParent, 0x80_00_00_00, @@ -221,13 +236,13 @@ describe('Secret Module Tests', () => { }).toMatchSnapshot('secp256k1-hardened-child-key'); }); - it('should match snapshot for ed25519', () => { + it('should match snapshot for ed25519', async () => { const encryptedParent = { key: encrypt(testPassword, testMasterKey.key), chainCode: testMasterKey.chainCode, }; - const hardenedChildKey = CKDPriv( + const hardenedChildKey = await CKDPriv( 'ed25519', encryptedParent, 0x80_00_00_00, @@ -239,24 +254,29 @@ describe('Secret Module Tests', () => { }).toMatchSnapshot('ed25519-hardened-child-key'); }); - it('should match snapshot for nistp256', () => { + it('should match snapshot for nistp256', async () => { const encryptedParent = { key: encrypt(testPassword, testMasterKey.key), chainCode: testMasterKey.chainCode, }; - const childKey = CKDPriv('nistp256', encryptedParent, 0, testPassword); + const childKey = await CKDPriv( + 'nistp256', + encryptedParent, + 0, + testPassword, + ); expect({ key: childKey.key.toString('hex'), chainCode: childKey.chainCode.toString('hex'), }).toMatchSnapshot('nistp256-child-key'); }); - it('should derive child private keys correctly using CKDPriv', () => { + it('should derive child private keys correctly using CKDPriv', async () => { const testMnemonic = 'test test test test test test test test test test test junk'; const rs = mnemonicToRevealableSeed(testMnemonic); - const hdCredential = encryptRevealableSeed({ + const hdCredential = await encryptRevealableSeed({ rs, password: testPassword, }); @@ -273,13 +293,13 @@ describe('Secret Module Tests', () => { entropyWithLangPrefixed: seedBuffer.toString('hex'), seed, }; - const encryptedSeed = encryptRevealableSeed({ + const encryptedSeed = await encryptRevealableSeed({ rs: revealableSeed, password: testPassword, }); // Generate master key from seed - const encryptedMasterKey = generateMasterKeyFromSeed( + const encryptedMasterKey = await generateMasterKeyFromSeed( 'secp256k1', encryptedSeed, testPassword, @@ -295,7 +315,7 @@ describe('Secret Module Tests', () => { expect(masterKey.key.length).toBe(32); expect(masterKey.chainCode.length).toBe(32); - const childKey = CKDPriv( + const childKey = await CKDPriv( 'secp256k1', encryptedMasterKey, 0, @@ -307,7 +327,7 @@ describe('Secret Module Tests', () => { // Test hardened index derivation const hardenedIndex = 2_147_483_648; // 2^31, first hardened index - const hardenedChild = CKDPriv( + const hardenedChild = await CKDPriv( 'secp256k1', encryptedMasterKey, hardenedIndex, @@ -331,7 +351,12 @@ describe('Secret Module Tests', () => { 'hex', ), }; - const nistChild = CKDPriv('nistp256', nistMasterKey, 0, testPassword); + const nistChild = await CKDPriv( + 'nistp256', + nistMasterKey, + 0, + testPassword, + ); expect(nistChild).toBeDefined(); const edMasterKey = { @@ -342,7 +367,7 @@ describe('Secret Module Tests', () => { chainCode: Buffer.from('0123456789abcdef0123456789abcdef', 'hex'), }; // ed25519 only supports hardened derivation - const edChild = CKDPriv( + const edChild = await CKDPriv( 'ed25519', edMasterKey, hardenedIndex, @@ -351,13 +376,15 @@ describe('Secret Module Tests', () => { expect(edChild).toBeDefined(); // Test error cases - expect(() => CKDPriv('ed25519', edMasterKey, 0, testPassword)).toThrow(); - expect(() => + await expect( + CKDPriv('ed25519', edMasterKey, 0, testPassword), + ).rejects.toThrow(); + await expect( CKDPriv('invalid-curve' as any, encryptedMasterKey, 0, testPassword), - ).toThrow(); - expect(() => + ).rejects.toThrow(); + await expect( CKDPriv('secp256k1', encryptedMasterKey, -1, testPassword), - ).toThrow(); + ).rejects.toThrow(); }); it('should handle async mnemonic and seed operations', async () => { @@ -368,7 +395,7 @@ describe('Secret Module Tests', () => { const testMnemonic = 'test test test test test test test test test test test junk'; const rs = mnemonicToRevealableSeed(testMnemonic, 'optional passphrase'); - const hdCredential = encryptRevealableSeed({ + const hdCredential = await encryptRevealableSeed({ rs, password, }); @@ -424,15 +451,17 @@ describe('Secret Module Tests', () => { ).rejects.toThrow(); }); - it('should throw error for invalid curve', () => { + it('should throw error for invalid curve', async () => { const encryptedParent = { key: encrypt(testPassword, testMasterKey.key), chainCode: testMasterKey.chainCode, }; - expect(() => { - CKDPriv('invalid-curve' as any, encryptedParent, 0, testPassword); - }).toThrow('Key derivation is not supported for curve invalid-curve.'); + await expect( + CKDPriv('invalid-curve' as any, encryptedParent, 0, testPassword), + ).rejects.toThrow( + 'Key derivation is not supported for curve invalid-curve.', + ); }); }); @@ -480,12 +509,12 @@ describe('Secret Module Tests', () => { const testMnemonic = 'test test test test test test test test test test test junk'; const rs = mnemonicToRevealableSeed(testMnemonic); - const hdCredential = encryptRevealableSeed({ - rs, - password: testPassword, - }); it('should generate fingerprint for secp256k1', async () => { + const hdCredential = await encryptRevealableSeed({ + rs, + password: testPassword, + }); const fingerprint = await generateRootFingerprintHexAsync({ curveName: 'secp256k1', hdCredential, @@ -496,6 +525,10 @@ describe('Secret Module Tests', () => { }); it('should generate fingerprint for different curves', async () => { + const hdCredential = await encryptRevealableSeed({ + rs, + password: testPassword, + }); const curves: ICurveName[] = ['secp256k1', 'nistp256', 'ed25519']; for (const curve of curves) { const fingerprint = await generateRootFingerprintHexAsync({ @@ -508,6 +541,10 @@ describe('Secret Module Tests', () => { }); it('should throw error for invalid curve', async () => { + const hdCredential = await encryptRevealableSeed({ + rs, + password: testPassword, + }); await expect( generateRootFingerprintHexAsync({ curveName: 'invalid-curve' as ICurveName, @@ -518,6 +555,10 @@ describe('Secret Module Tests', () => { }); it('should throw error for invalid password', async () => { + const hdCredential = await encryptRevealableSeed({ + rs, + password: testPassword, + }); await expect( generateRootFingerprintHexAsync({ curveName: 'secp256k1', @@ -528,6 +569,11 @@ describe('Secret Module Tests', () => { }); it('should match snapshot', async () => { + const hdCredential = await encryptRevealableSeed({ + rs, + password: testPassword, + }); + const fingerprint = await generateRootFingerprintHexAsync({ curveName: 'secp256k1', hdCredential, @@ -595,17 +641,17 @@ describe('Secret Module Tests', () => { seed: '00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff', }; - const encryptedSeed = encryptRevealableSeed({ - rs: testSeed, - password: testPassword, - }); + it('should derive private keys for valid paths', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); - it('should derive private keys for valid paths', () => { const curveName: ICurveName = 'secp256k1'; const prefix = 'm'; const relPaths = ['0/0', '0/1', "44'/0'/0'/0/0"]; - const privateKeys = batchGetPrivateKeys( + const privateKeys = await batchGetPrivateKeys( curveName, encryptedSeed, testPassword, @@ -626,12 +672,16 @@ describe('Secret Module Tests', () => { }); }); - it('should throw error for invalid curve name', () => { + it('should throw error for invalid curve name', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName = 'invalid-curve' as ICurveName; const prefix = 'm'; const relPaths = ['0/0']; - expect(() => + await expect( batchGetPrivateKeys( curveName, encryptedSeed, @@ -639,15 +689,21 @@ describe('Secret Module Tests', () => { prefix, relPaths, ), - ).toThrow('Key derivation is not supported for curve invalid-curve.'); + ).rejects.toThrow( + 'Key derivation is not supported for curve invalid-curve.', + ); }); - it('should throw error for invalid password', () => { + it('should throw error for invalid password', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName: ICurveName = 'secp256k1'; const prefix = 'm'; const relPaths = ['0/0']; - expect(() => + await expect( batchGetPrivateKeys( curveName, encryptedSeed, @@ -655,15 +711,19 @@ describe('Secret Module Tests', () => { prefix, relPaths, ), - ).toThrow(); + ).rejects.toThrow(); }); - it('should handle hardened and non-hardened derivation paths', () => { + it('should handle hardened and non-hardened derivation paths', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName: ICurveName = 'secp256k1'; const prefix = 'm'; const relPaths = ["44'/0'", '0/0', "1'/0/0"]; - const privateKeys = batchGetPrivateKeys( + const privateKeys = await batchGetPrivateKeys( curveName, encryptedSeed, testPassword, @@ -677,12 +737,16 @@ describe('Secret Module Tests', () => { expect(privateKeys[2].path).toBe("m/1'/0/0"); }); - it('should match snapshot', () => { + it('should match snapshot', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName: ICurveName = 'secp256k1'; const prefix = 'm'; const relPaths = ['0/0']; - const privateKeys = batchGetPrivateKeys( + const privateKeys = await batchGetPrivateKeys( curveName, encryptedSeed, testPassword, @@ -710,17 +774,16 @@ describe('Secret Module Tests', () => { seed: '00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff', }; - const encryptedSeed = encryptRevealableSeed({ - rs: testSeed, - password: testPassword, - }); - - it('should generate public keys matching private keys', () => { + it('should generate public keys matching private keys', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName: ICurveName = 'secp256k1'; const prefix = 'm'; const relPaths = ['0/0', '0/1', "44'/0'/0'/0/0"]; - const privateKeys = batchGetPrivateKeys( + const privateKeys = await batchGetPrivateKeys( curveName, encryptedSeed, testPassword, @@ -728,7 +791,7 @@ describe('Secret Module Tests', () => { relPaths, ); - const publicKeys = batchGetPublicKeys( + const publicKeys = await batchGetPublicKeys( curveName, encryptedSeed, testPassword, @@ -751,12 +814,16 @@ describe('Secret Module Tests', () => { }); }); - it('should throw error for invalid curve name', () => { + it('should throw error for invalid curve name', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName = 'invalid-curve' as ICurveName; const prefix = 'm'; const relPaths = ['0/0']; - expect(() => + await expect( batchGetPublicKeys( curveName, encryptedSeed, @@ -764,15 +831,21 @@ describe('Secret Module Tests', () => { prefix, relPaths, ), - ).toThrow('Key derivation is not supported for curve invalid-curve.'); + ).rejects.toThrow( + 'Key derivation is not supported for curve invalid-curve.', + ); }); - it('should throw error for invalid password', () => { + it('should throw error for invalid password', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName: ICurveName = 'secp256k1'; const prefix = 'm'; const relPaths = ['0/0']; - expect(() => + await expect( batchGetPublicKeys( curveName, encryptedSeed, @@ -780,15 +853,19 @@ describe('Secret Module Tests', () => { prefix, relPaths, ), - ).toThrow(); + ).rejects.toThrow(); }); - it('should handle hardened and non-hardened derivation paths', () => { + it('should handle hardened and non-hardened derivation paths', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName: ICurveName = 'secp256k1'; const prefix = 'm'; const relPaths = ["44'/0'", '0/0', "1'/0/0"]; - const publicKeys = batchGetPublicKeys( + const publicKeys = await batchGetPublicKeys( curveName, encryptedSeed, testPassword, @@ -802,12 +879,16 @@ describe('Secret Module Tests', () => { expect(publicKeys[2].path).toBe("m/1'/0/0"); }); - it('should match snapshot', () => { + it('should match snapshot', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName: ICurveName = 'secp256k1'; const prefix = 'm'; const relPaths = ['0/0']; - const publicKeys = batchGetPublicKeys( + const publicKeys = await batchGetPublicKeys( curveName, encryptedSeed, testPassword, @@ -835,21 +916,20 @@ describe('Secret Module Tests', () => { seed: '00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff', }; - const encryptedSeed = encryptRevealableSeed({ - rs: testSeed, - password: testPassword, - }); - beforeEach(() => { // do nothing }); it('should return same results as batchGetPublicKeys in non-native environment', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const curveName: ICurveName = 'secp256k1'; const prefix = 'm'; const relPaths = ['0/0', '0/1', "44'/0'/0'/0/0"]; - const syncResult = batchGetPublicKeys( + const syncResult = await batchGetPublicKeys( curveName, encryptedSeed, testPassword, @@ -869,6 +949,10 @@ describe('Secret Module Tests', () => { }); it('should handle native environment correctly', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const result = await batchGetPublicKeysAsync({ curveName: 'secp256k1', hdCredential: encryptedSeed, @@ -892,6 +976,10 @@ describe('Secret Module Tests', () => { }); it('should match snapshot', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testSeed, + password: testPassword, + }); const result = await batchGetPublicKeysAsync({ curveName: 'secp256k1', hdCredential: encryptedSeed, @@ -969,9 +1057,9 @@ describe('Secret Module Tests', () => { privateKey: '0123456789abcdef', }; - it('should decrypt imported credential correctly', () => { + it('should decrypt imported credential correctly', async () => { // First encrypt the credential - const encryptedCredential = encryptImportedCredential({ + const encryptedCredential = await encryptImportedCredential({ credential: testCredential, password: testPassword, }); @@ -985,8 +1073,8 @@ describe('Secret Module Tests', () => { expect(decryptedCredential).toEqual(testCredential); }); - it('should handle credential with prefix correctly', () => { - const encryptedCredential = encryptImportedCredential({ + it('should handle credential with prefix correctly', async () => { + const encryptedCredential = await encryptImportedCredential({ credential: testCredential, password: testPassword, }); @@ -1001,8 +1089,8 @@ describe('Secret Module Tests', () => { expect(decryptedCredential).toEqual(testCredential); }); - it('should throw error for invalid password', () => { - const encryptedCredential = encryptImportedCredential({ + it('should throw error for invalid password', async () => { + const encryptedCredential = await encryptImportedCredential({ credential: testCredential, password: testPassword, }); @@ -1024,8 +1112,8 @@ describe('Secret Module Tests', () => { ).toThrow(); }); - it('should match snapshot for decrypted credential', () => { - const encryptedCredential = encryptImportedCredential({ + it('should match snapshot for decrypted credential', async () => { + const encryptedCredential = await encryptImportedCredential({ credential: testCredential, password: testPassword, }); @@ -1046,9 +1134,9 @@ describe('Secret Module Tests', () => { seed: '00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff', }; - it('should decrypt revealable seed correctly', () => { + it('should decrypt revealable seed correctly', async () => { // First encrypt the seed - const encryptedSeed = encryptRevealableSeed({ + const encryptedSeed = await encryptRevealableSeed({ rs: testSeed, password: testPassword, }); @@ -1062,8 +1150,8 @@ describe('Secret Module Tests', () => { expect(decryptedSeed).toEqual(testSeed); }); - it('should throw error for invalid password', () => { - const encryptedSeed = encryptRevealableSeed({ + it('should throw error for invalid password', async () => { + const encryptedSeed = await encryptRevealableSeed({ rs: testSeed, password: testPassword, }); @@ -1085,8 +1173,8 @@ describe('Secret Module Tests', () => { ).toThrow(); }); - it('should match snapshot for decrypted seed', () => { - const encryptedSeed = encryptRevealableSeed({ + it('should match snapshot for decrypted seed', async () => { + const encryptedSeed = await encryptRevealableSeed({ rs: testSeed, password: testPassword, }); @@ -1103,9 +1191,9 @@ describe('Secret Module Tests', () => { describe('decryptVerifyString', () => { const testPassword = 'test123'; - it('should decrypt verify string correctly', () => { + it('should decrypt verify string correctly', async () => { // First encrypt the string - const encryptedString = encryptVerifyString({ + const encryptedString = await encryptVerifyString({ password: testPassword, }); @@ -1118,8 +1206,8 @@ describe('Secret Module Tests', () => { expect(decryptedString).toBe(DEFAULT_VERIFY_STRING); }); - it('should handle string with prefix correctly', () => { - const encryptedString = encryptVerifyString({ + it('should handle string with prefix correctly', async () => { + const encryptedString = await encryptVerifyString({ password: testPassword, addPrefixString: true, }); @@ -1134,8 +1222,8 @@ describe('Secret Module Tests', () => { expect(decryptedString).toBe(DEFAULT_VERIFY_STRING); }); - it('should throw error for invalid password', () => { - const encryptedString = encryptVerifyString({ + it('should throw error for invalid password', async () => { + const encryptedString = await encryptVerifyString({ password: testPassword, }); @@ -1156,8 +1244,8 @@ describe('Secret Module Tests', () => { ).toThrow(); }); - it('should match snapshot for decrypted string', () => { - const encryptedString = encryptVerifyString({ + it('should match snapshot for decrypted string', async () => { + const encryptedString = await encryptVerifyString({ password: testPassword, }); @@ -1176,8 +1264,8 @@ describe('Secret Module Tests', () => { privateKey: '0123456789abcdef', }; - it('should encrypt credential correctly', () => { - const encryptedCredential = encryptImportedCredential({ + it('should encrypt credential correctly', async () => { + const encryptedCredential = await encryptImportedCredential({ credential: testCredential, password: testPassword, }); @@ -1193,13 +1281,13 @@ describe('Secret Module Tests', () => { expect(decryptedCredential).toEqual(testCredential); }); - it('should handle different private key formats', () => { + it('should handle different private key formats', async () => { const longKeyCredential: ICoreImportedCredential = { privateKey: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', }; - const encryptedCredential = encryptImportedCredential({ + const encryptedCredential = await encryptImportedCredential({ credential: longKeyCredential, password: testPassword, }); @@ -1212,21 +1300,21 @@ describe('Secret Module Tests', () => { expect(decryptedCredential).toEqual(longKeyCredential); }); - it('should throw error for empty private key', () => { + it('should throw error for empty private key', async () => { const invalidCredential = { privateKey: '', }; - expect(() => + await expect( encryptImportedCredential({ credential: invalidCredential as ICoreImportedCredential, password: testPassword, }), - ).toThrow(); + ).rejects.toThrow(); }); - it('should match snapshot', () => { - const encryptedCredential = encryptImportedCredential({ + it('should match snapshot', async () => { + const encryptedCredential = await encryptImportedCredential({ credential: testCredential, password: testPassword, }); @@ -1242,8 +1330,8 @@ describe('Secret Module Tests', () => { seed: 'deadbeefdeadbeefdeadbeefdeadbeef', }; - it('should encrypt seed correctly', () => { - const encryptedSeed = encryptRevealableSeed({ + it('should encrypt seed correctly', async () => { + const encryptedSeed = await encryptRevealableSeed({ rs: testSeed, password: testPassword, }); @@ -1257,14 +1345,14 @@ describe('Secret Module Tests', () => { expect(decryptedSeed).toEqual(testSeed); }); - it('should handle different seed lengths', () => { + it('should handle different seed lengths', async () => { const longSeed: IBip39RevealableSeed = { entropyWithLangPrefixed: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', seed: 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef', }; - const encryptedSeed = encryptRevealableSeed({ + const encryptedSeed = await encryptRevealableSeed({ rs: longSeed, password: testPassword, }); @@ -1277,22 +1365,22 @@ describe('Secret Module Tests', () => { expect(decryptedSeed).toEqual(longSeed); }); - it('should throw error for invalid seed object', () => { + it('should throw error for invalid seed object', async () => { const invalidSeed = { entropyWithLangPrefixed: '', seed: '', }; - expect(() => + await expect( encryptRevealableSeed({ rs: invalidSeed as IBip39RevealableSeed, password: testPassword, }), - ).toThrow(); + ).rejects.toThrow(); }); - it('should match snapshot', () => { - const encryptedSeed = encryptRevealableSeed({ + it('should match snapshot', async () => { + const encryptedSeed = await encryptRevealableSeed({ rs: testSeed, password: testPassword, }); @@ -1362,8 +1450,8 @@ describe('Secret Module Tests', () => { describe('encryptVerifyString', () => { const testPassword = 'test123'; - it('should encrypt string correctly', () => { - const encryptedString = encryptVerifyString({ + it('should encrypt string correctly', async () => { + const encryptedString = await encryptVerifyString({ password: testPassword, }); @@ -1376,15 +1464,15 @@ describe('Secret Module Tests', () => { expect(decryptedString).toBe('OneKey'); }); - it('should handle prefix option', () => { - const withPrefix = encryptVerifyString({ + it('should handle prefix option', async () => { + const withPrefix = await encryptVerifyString({ password: testPassword, addPrefixString: true, }); expect(withPrefix.startsWith('|VS|')).toBe(true); - const withoutPrefix = encryptVerifyString({ + const withoutPrefix = await encryptVerifyString({ password: testPassword, addPrefixString: false, }); @@ -1407,16 +1495,16 @@ describe('Secret Module Tests', () => { ).toBe('OneKey'); }); - it('should throw error for empty password', () => { - expect(() => + it('should throw error for empty password', async () => { + await expect( encryptVerifyString({ password: '', }), - ).toThrow(); + ).rejects.toThrow(); }); - it('should match snapshot', () => { - const encryptedString = encryptVerifyString({ + it('should match snapshot', async () => { + const encryptedString = await encryptVerifyString({ password: testPassword, }); @@ -1450,7 +1538,7 @@ describe('Secret Module Tests', () => { expect(result).toBe('|VS|abc123'); }); - it('should match snapshot', () => { + it('should match snapshot', async () => { const result = fixV4VerifyStringToV5({ verifyString: 'test123', }); @@ -1461,13 +1549,13 @@ describe('Secret Module Tests', () => { describe('generateMasterKeyFromSeed', () => { const testRevealableSeed = mnemonicToRevealableSeed(TEST_MNEMONIC); - const encryptedSeed = encryptRevealableSeed({ - rs: testRevealableSeed, - password: TEST_PASSWORD, - }); + it('should generate master key for secp256k1', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testRevealableSeed, + password: TEST_PASSWORD, + }); - it('should generate master key for secp256k1', () => { - const masterKey = generateMasterKeyFromSeed( + const masterKey = await generateMasterKeyFromSeed( 'secp256k1', encryptedSeed, TEST_PASSWORD, @@ -1478,8 +1566,12 @@ describe('Secret Module Tests', () => { expect(masterKey.chainCode.length).toBe(32); }); - it('should generate master key for nistp256', () => { - const masterKey = generateMasterKeyFromSeed( + it('should generate master key for nistp256', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testRevealableSeed, + password: TEST_PASSWORD, + }); + const masterKey = await generateMasterKeyFromSeed( 'nistp256', encryptedSeed, TEST_PASSWORD, @@ -1490,8 +1582,12 @@ describe('Secret Module Tests', () => { expect(masterKey.chainCode.length).toBe(32); }); - it('should generate master key for ed25519', () => { - const masterKey = generateMasterKeyFromSeed( + it('should generate master key for ed25519', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testRevealableSeed, + password: TEST_PASSWORD, + }); + const masterKey = await generateMasterKeyFromSeed( 'ed25519', encryptedSeed, TEST_PASSWORD, @@ -1502,24 +1598,38 @@ describe('Secret Module Tests', () => { expect(masterKey.chainCode.length).toBe(32); }); - it('should throw error for invalid curve', () => { - expect(() => { + it('should throw error for invalid curve', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testRevealableSeed, + password: TEST_PASSWORD, + }); + await expect( generateMasterKeyFromSeed( 'invalid-curve' as any, encryptedSeed, TEST_PASSWORD, - ); - }).toThrow('Key derivation is not supported for curve invalid-curve.'); + ), + ).rejects.toThrow( + 'Key derivation is not supported for curve invalid-curve.', + ); }); - it('should throw error for invalid password', () => { - expect(() => { - generateMasterKeyFromSeed('secp256k1', encryptedSeed, 'wrong-password'); - }).toThrow('IncorrectPassword'); + it('should throw error for invalid password', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testRevealableSeed, + password: TEST_PASSWORD, + }); + await expect( + generateMasterKeyFromSeed('secp256k1', encryptedSeed, 'wrong-password'), + ).rejects.toThrow('IncorrectPassword'); }); - it('should match snapshot', () => { - const masterKey = generateMasterKeyFromSeed( + it('should match snapshot', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testRevealableSeed, + password: TEST_PASSWORD, + }); + const masterKey = await generateMasterKeyFromSeed( 'secp256k1', encryptedSeed, TEST_PASSWORD, @@ -1534,12 +1644,11 @@ describe('Secret Module Tests', () => { describe('mnemonicFromEntropyAsync', () => { const testRevealableSeed = mnemonicToRevealableSeed(TEST_MNEMONIC); - const encryptedSeed = encryptRevealableSeed({ - rs: testRevealableSeed, - password: TEST_PASSWORD, - }); - it('should generate mnemonic from entropy', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testRevealableSeed, + password: TEST_PASSWORD, + }); const mnemonic = await mnemonicFromEntropyAsync({ hdCredential: encryptedSeed, password: TEST_PASSWORD, @@ -1549,6 +1658,10 @@ describe('Secret Module Tests', () => { }); it('should throw error for invalid password', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testRevealableSeed, + password: TEST_PASSWORD, + }); await expect( mnemonicFromEntropyAsync({ hdCredential: encryptedSeed, @@ -1558,6 +1671,10 @@ describe('Secret Module Tests', () => { }); it('should match snapshot', async () => { + const encryptedSeed = await encryptRevealableSeed({ + rs: testRevealableSeed, + password: TEST_PASSWORD, + }); const mnemonic = await mnemonicFromEntropyAsync({ hdCredential: encryptedSeed, password: TEST_PASSWORD, @@ -1718,17 +1835,13 @@ describe('Secret Module Tests', () => { describe('tonMnemonicFromEntropy', () => { const testPassword = 'test123'; - const encryptedSeed = revealableSeedFromTonMnemonic( - TEST_TON_MNEMONIC, - testPassword, - ); - const encryptedSeed2 = revealableSeedFromTonMnemonic( - TEST_TON_MNEMONIC2, - testPassword, - ); // const revealableSeed = tonMnemonicToRevealableSeed(TEST_TON_MNEMONIC); - it('should generate valid TON mnemonic from entropy', () => { + it('should generate valid TON mnemonic from entropy', async () => { + const encryptedSeed = await revealableSeedFromTonMnemonic( + TEST_TON_MNEMONIC, + testPassword, + ); const mnemonic = tonMnemonicFromEntropy(encryptedSeed, testPassword); expect(typeof mnemonic).toBe('string'); expect(mnemonic.split(' ').length).toBe(24); // TON uses 24 words @@ -1749,7 +1862,15 @@ describe('Secret Module Tests', () => { ).toThrow(); }); - it('should generate different mnemonics for different entropy', () => { + it('should generate different mnemonics for different entropy', async () => { + const encryptedSeed = await revealableSeedFromTonMnemonic( + TEST_TON_MNEMONIC, + testPassword, + ); + const encryptedSeed2 = await revealableSeedFromTonMnemonic( + TEST_TON_MNEMONIC2, + testPassword, + ); const mnemonic1 = tonMnemonicFromEntropy(encryptedSeed, testPassword); const mnemonic2 = tonMnemonicFromEntropy(encryptedSeed2, testPassword); @@ -1758,19 +1879,32 @@ describe('Secret Module Tests', () => { expect(mnemonic2).toMatchSnapshot('ton-mnemonic-2'); }); - it('should convert entropy to TON mnemonic', () => { + it('should convert entropy to TON mnemonic', async () => { + const encryptedSeed = await revealableSeedFromTonMnemonic( + TEST_TON_MNEMONIC, + testPassword, + ); + const mnemonic = tonMnemonicFromEntropy(encryptedSeed, testPassword); expect(typeof mnemonic).toBe('string'); expect(mnemonic.split(' ').length).toBe(24); // TON uses 24 words }); - it('should throw error for invalid password', () => { + it('should throw error for invalid password', async () => { + const encryptedSeed = await revealableSeedFromTonMnemonic( + TEST_TON_MNEMONIC, + testPassword, + ); expect(() => tonMnemonicFromEntropy(encryptedSeed, 'wrong-password'), ).toThrow(); }); - it('should match snapshot', () => { + it('should match snapshot', async () => { + const encryptedSeed = await revealableSeedFromTonMnemonic( + TEST_TON_MNEMONIC, + testPassword, + ); const mnemonic = tonMnemonicFromEntropy(encryptedSeed, testPassword); expect(mnemonic).toMatchSnapshot(); }); @@ -1781,8 +1915,8 @@ describe('Secret Module Tests', () => { const testMnemonic = 'abandon math mimic master filter design carbon crystal rookie group knife young abandon math mimic master filter design carbon crystal rookie group knife young abandon today'; - it('should convert TON mnemonic to revealable seed with proper UTF-8 encoding', () => { - const encryptedSeed = revealableSeedFromTonMnemonic( + it('should convert TON mnemonic to revealable seed with proper UTF-8 encoding', async () => { + const encryptedSeed = await revealableSeedFromTonMnemonic( testMnemonic, testPassword, ); @@ -1803,21 +1937,21 @@ describe('Secret Module Tests', () => { }); // TODO: revealableSeedFromTonMnemonic should validate mnemonic before return, should make it async - it.skip('should throw InvalidMnemonic for malformed input', () => { - expect(() => revealableSeedFromTonMnemonic('', testPassword)).toThrow( - 'Invalid seed object', - ); - expect(() => + it.skip('should throw InvalidMnemonic for malformed input', async () => { + await expect( + revealableSeedFromTonMnemonic('', testPassword), + ).rejects.toThrow('Invalid seed object'); + await expect( revealableSeedFromTonMnemonic('invalid mnemonic', testPassword), - ).toThrow(InvalidMnemonic); + ).rejects.toThrow(InvalidMnemonic); // Test with non-UTF8 characters - expect(() => + await expect( revealableSeedFromTonMnemonic('\uD800', testPassword), - ).toThrow(InvalidMnemonic); + ).rejects.toThrow(InvalidMnemonic); }); - it('should match snapshot', () => { - const encryptedSeed = revealableSeedFromTonMnemonic( + it('should match snapshot', async () => { + const encryptedSeed = await revealableSeedFromTonMnemonic( testMnemonic, testPassword, ); diff --git a/packages/core/src/secret/bip32.ts b/packages/core/src/secret/bip32.ts index 99a403b1caf..baf9261ec91 100644 --- a/packages/core/src/secret/bip32.ts +++ b/packages/core/src/secret/bip32.ts @@ -26,7 +26,7 @@ function serNum(p: BigNumber, bits: 32 | 256): Buffer { } function ser32(index: number): Buffer { - if (!Number.isInteger(index)) { + if (typeof index !== 'number' || !Number.isInteger(index) || index < 0) { throw Error('Invalid index.'); } diff --git a/packages/core/src/secret/encryptors/__tests__/aes256.test.ts b/packages/core/src/secret/encryptors/__tests__/aes256.test.ts new file mode 100644 index 00000000000..158457b288b --- /dev/null +++ b/packages/core/src/secret/encryptors/__tests__/aes256.test.ts @@ -0,0 +1,136 @@ +import { + decrypt, + decryptString, + encrypt, + encryptAsync, + encryptString, + encryptStringAsync, +} from '../aes256'; + +/* run test ============================== + +yarn jest packages/core/src/secret/encryptors/__tests__/aes256.test.ts + +*/ + +describe('aes256', () => { + const testPassword = 'testPassword123'; + const testData = 'Hello, World!'; + const testBuffer = Buffer.from(testData); + + describe('encrypt/decrypt', () => { + it('should encrypt and decrypt data correctly using sync methods', () => { + const encrypted = encrypt(testPassword, testBuffer, true); + const decrypted = decrypt(testPassword, encrypted, false, true); + expect(decrypted.toString()).toBe(testData); + }); + + it('should encrypt and decrypt data correctly using async methods', async () => { + const encrypted = await encryptAsync({ + password: testPassword, + data: testBuffer, + }); + const decrypted = decrypt(testPassword, encrypted, false, true); + expect(decrypted.toString()).toBe(testData); + }); + + it('should produce different ciphertexts for same input', async () => { + const encrypted1 = await encryptAsync({ + password: testPassword, + data: testBuffer, + }); + const encrypted2 = await encryptAsync({ + password: testPassword, + data: testBuffer, + }); + expect(encrypted1.toString('hex')).not.toBe(encrypted2.toString('hex')); + }); + }); + + describe('encryptString/decryptString', () => { + it('should encrypt and decrypt strings correctly using sync methods', () => { + const encrypted = encryptString({ + password: testPassword, + data: testData, + dataEncoding: 'utf8', + allowRawPassword: true, + }); + console.log('encrypted', encrypted); + const decrypted = decryptString({ + password: testPassword, + data: encrypted, + dataEncoding: 'hex', + resultEncoding: 'utf8', + allowRawPassword: true, + }); + expect(decrypted).toBe(testData); + }); + + it('should encrypt and decrypt strings correctly using async methods', async () => { + const encrypted = await encryptStringAsync({ + password: testPassword, + data: testData, + dataEncoding: 'utf8', + allowRawPassword: true, + }); + const decrypted = decryptString({ + password: testPassword, + data: encrypted, + dataEncoding: 'hex', + resultEncoding: 'utf8', + allowRawPassword: true, + }); + expect(decrypted).toBe(testData); + }); + + it('should handle different encodings correctly', async () => { + const hexData = Buffer.from(testData).toString('hex'); + const encrypted = await encryptStringAsync({ + password: testPassword, + data: hexData, + dataEncoding: 'hex', + allowRawPassword: true, + }); + const decrypted = decryptString({ + password: testPassword, + data: encrypted, + dataEncoding: 'hex', + resultEncoding: 'hex', + allowRawPassword: true, + }); + expect(Buffer.from(decrypted, 'hex').toString()).toBe(testData); + }); + }); + + describe('deprecation warnings', () => { + const originalWarn = console.warn; + let warnMock: jest.Mock; + + beforeEach(() => { + warnMock = jest.fn(); + console.warn = warnMock; + }); + + afterEach(() => { + console.warn = originalWarn; + }); + + it('should show deprecation warning for sync encrypt', () => { + encrypt(testPassword, testBuffer); + expect(warnMock).toHaveBeenCalledWith( + expect.stringContaining('deprecated'), + ); + }); + + it('should show deprecation warning for sync encryptString', () => { + encryptString({ + password: testPassword, + data: testData, + dataEncoding: 'utf8', + }); + expect(warnMock).toHaveBeenCalledWith( + expect.stringContaining('deprecated'), + ); + }); + }); +}); diff --git a/packages/core/src/secret/encryptors/aes256.ts b/packages/core/src/secret/encryptors/aes256.ts index 3c2fc3b7b55..bf1324da9c7 100644 --- a/packages/core/src/secret/encryptors/aes256.ts +++ b/packages/core/src/secret/encryptors/aes256.ts @@ -96,13 +96,13 @@ function decodePassword({ return password; } -function encodePassword({ +async function encodePassword({ password, key, }: { password: string; key?: string; -}): string { +}): Promise { // eslint-disable-next-line @typescript-eslint/no-use-before-define return encodeSensitiveText({ text: password, @@ -110,17 +110,29 @@ function encodePassword({ }); } +// ------------------------------------------------------------ + +/** + * @deprecated Use encryptAsync instead. This synchronous encryption method will be removed in a future version. + * @see encryptAsync + */ function encrypt( password: string, data: Buffer | string, allowRawPassword?: boolean, ): Buffer { + console.warn('encrypt() is deprecated. Please use encryptAsync() instead'); + // eslint-disable-next-line no-console + console.trace('encrypt() call stack'); if (!password) { throw new IncorrectPassword(); } const dataBuffer = bufferUtils.toBuffer(data); // eslint-disable-next-line no-param-reassign const passwordDecoded = decodePassword({ password, allowRawPassword }); + if (!passwordDecoded) { + throw new IncorrectPassword(); + } const salt: Buffer = crypto.randomBytes(PBKDF2_SALT_LENGTH); const key: Buffer = keyFromPasswordAndSalt(passwordDecoded, salt); const iv: Buffer = crypto.randomBytes(AES256_IV_LENGTH); @@ -131,31 +143,58 @@ function encrypt( ]); } +// ------------------------------------------------------------ + export type IEncryptStringParams = { password: string; data: string; dataEncoding?: BufferEncoding; + allowRawPassword?: boolean; }; + +/** + * @deprecated Use encryptStringAsync instead. This synchronous encryption method will be removed in a future version. + * @see encryptStringAsync + */ function encryptString({ password, data, dataEncoding = 'hex', + allowRawPassword, }: IEncryptStringParams): string { - const bytes = encrypt(password, bufferUtils.toBuffer(data, dataEncoding)); + console.warn( + 'encryptString() is deprecated. Please use encryptStringAsync() instead', + ); + // eslint-disable-next-line no-console + console.trace('encryptString() call stack'); + const bytes = encrypt( + password, + bufferUtils.toBuffer(data, dataEncoding), + allowRawPassword, + ); return bufferUtils.bytesToHex(bytes); } +// ------------------------------------------------------------ async function encryptAsync({ password, data, + allowRawPassword, }: { password: string; data: Buffer | string; + allowRawPassword?: boolean; }): Promise { - // eslint-disable-next-line no-param-reassign - const passwordDecoded = decodePassword({ password }); + if (!password) { + throw new IncorrectPassword(); + } + + const passwordDecoded = decodePassword({ password, allowRawPassword }); + const dataBuffer = bufferUtils.toBuffer(data); if (platformEnv.isNative && !platformEnv.isJest) { + // call appGlobals.$webembedApiProxy.secret.encryptAsync() + throw new Error('webembedApiProxy not ready yet'); // const webembedApiProxy = ( // await import('@onekeyhq/kit-bg/src/webembeds/instance/webembedApiProxy') @@ -167,7 +206,14 @@ async function encryptAsync({ // return bufferUtils.toBuffer(str, 'hex'); } - return Promise.resolve(encrypt(passwordDecoded, data)); + const salt: Buffer = crypto.randomBytes(PBKDF2_SALT_LENGTH); + const key: Buffer = keyFromPasswordAndSalt(passwordDecoded, salt); + const iv: Buffer = crypto.randomBytes(AES256_IV_LENGTH); + return Buffer.concat([ + salt, + iv, + Buffer.from(AES_CBC.encrypt(dataBuffer, key, true, iv)), + ]); } function decrypt( @@ -191,6 +237,9 @@ function decrypt( ignoreLogger: true, allowRawPassword, }); + if (!passwordDecoded) { + throw new IncorrectPassword(); + } if (!ignoreLogger) { defaultLogger.account.secretPerf.decodePasswordDone(); } @@ -251,6 +300,8 @@ async function decryptAsync({ const passwordDecoded = decodePassword({ password }); if (platformEnv.isNative && !platformEnv.isJest) { + // call appGlobals.$webembedApiProxy.secret.decryptAsync() + throw new Error('webembedApiProxy not ready yet'); // const webembedApiProxy = ( // await import('@onekeyhq/kit-bg/src/webembeds/instance/webembedApiProxy') @@ -270,20 +321,42 @@ export type IDecryptStringParams = { data: string; resultEncoding?: BufferEncoding; dataEncoding?: BufferEncoding; + allowRawPassword?: boolean; }; function decryptString({ password, data, resultEncoding = 'hex', dataEncoding = 'hex', + allowRawPassword, }: IDecryptStringParams): string { - const bytes = decrypt(password, bufferUtils.toBuffer(data, dataEncoding)); + const bytes = decrypt( + password, + bufferUtils.toBuffer(data, dataEncoding), + undefined, + allowRawPassword, + ); if (resultEncoding === 'hex') { return bufferUtils.bytesToHex(bytes); } return bufferUtils.bytesToText(bytes, resultEncoding); } +async function encryptStringAsync({ + password, + data, + dataEncoding = 'hex', + allowRawPassword, +}: IEncryptStringParams): Promise { + const bufferData = bufferUtils.toBuffer(data, dataEncoding); + const bytes = await encryptAsync({ + password, + data: bufferData, + allowRawPassword, + }); + return bufferUtils.bytesToHex(bytes); +} + function checkKeyPassedOnExtUi(key?: string) { if (platformEnv.isExtensionUi && !key) { throw new Error( @@ -334,7 +407,13 @@ function decodeSensitiveText({ throw new Error('Not correct encoded text'); } -function encodeSensitiveText({ text, key }: { text: string; key?: string }) { +async function encodeSensitiveText({ + text, + key, +}: { + text: string; + key?: string; +}) { checkKeyPassedOnExtUi(key); const theKey = key || encodeKey; ensureEncodeKeyExists(theKey); @@ -353,9 +432,16 @@ function encodeSensitiveText({ text, key }: { text: string; key?: string }) { // *** aes encode if (SENSITIVE_ENCODE_TYPE === 'aes') { - const encoded = encrypt(theKey, Buffer.from(text, 'utf-8'), true).toString( - 'hex', - ); + // const encoded = encrypt(theKey, Buffer.from(text, 'utf-8'), true).toString( + // 'hex', + // ); + const encoded = ( + await encryptAsync({ + password: theKey, + data: Buffer.from(text, 'utf-8'), + allowRawPassword: true, + }) + ).toString('hex'); return `${ENCODE_TEXT_PREFIX.aes}${encoded}`; } @@ -405,6 +491,7 @@ export { encrypt, encryptAsync, encryptString, + encryptStringAsync, ensureSensitiveTextEncoded, getBgSensitiveTextEncodeKey, isEncodedSensitiveText, diff --git a/packages/core/src/secret/index.test.ts b/packages/core/src/secret/index.test.ts index 0e88368c657..2b66a488f02 100644 --- a/packages/core/src/secret/index.test.ts +++ b/packages/core/src/secret/index.test.ts @@ -10,12 +10,17 @@ import { } from '@onekeyhq/shared/src/errors'; import bufferUtils from '@onekeyhq/shared/src/utils/bufferUtils'; -import { decrypt, encrypt } from './encryptors/aes256'; +import { decrypt, encryptAsync } from './encryptors/aes256'; import { sha256 } from './hash'; import type { ICurveName } from '../types'; -// yarn jest packages/core/src/secret/index.test.ts +/* run test ============================== + +yarn jest packages/core/src/secret/index.test.ts + +*/ + const halfNs: Record = { // eslint-disable-next-line new-cap secp256k1: new BigNumber(new elliptic.ec('secp256k1').nh.toString()), @@ -570,10 +575,14 @@ const bip39TestVectors = [ ]; const password = 'onekey'; -const xPrvTest = { + +const createXPrvTestAsync = async () => ({ chainCode: Buffer.alloc(32), - key: encrypt(password, Buffer.alloc(32)), -}; + key: await encryptAsync({ + password, + data: Buffer.alloc(32), + }), +}); const xPubTest = { chainCode: Buffer.alloc(32), @@ -593,19 +602,23 @@ test('Empty buffer not allowed', () => { }).toThrow(new Error('Curve call ERROR: Buffer is empty')); }); -test('Child index is not int', () => { - expect(() => { - CKDPriv('secp256k1', xPrvTest, 1.1, password); - }).toThrow(new Error('Invalid index.')); +test('Child index is not int', async () => { + const xPrvTest = await createXPrvTestAsync(); + await expect(CKDPriv('secp256k1', xPrvTest, 1.1, password)).rejects.toThrow( + new Error('Invalid index.'), + ); }); -test('Child index too big', () => { - expect(() => { - CKDPriv('secp256k1', xPrvTest, 2 ** 32, password); - }).toThrow(new Error('Overflowed.')); - expect(() => { - CKDPub('secp256k1', xPubTest, 2 ** 32); - }).toThrow(new Error('Invalid index.')); +test('Child index too big', async () => { + const xPrvTest = await createXPrvTestAsync(); + + await expect( + CKDPriv('secp256k1', xPrvTest, 2 ** 32, password), + ).rejects.toThrow(new Error('Overflowed.')); + + expect(() => CKDPub('secp256k1', xPubTest, 2 ** 32)).toThrow( + new Error('Invalid index.'), + ); }); test('(ECDSA) CKDPub failed for hardened index', () => { @@ -615,10 +628,12 @@ test('(ECDSA) CKDPub failed for hardened index', () => { }).toThrow(new Error(`Can't derive public key for index ${index}.`)); }); -test('Normal CKDPriv is not supported for ed25519', () => { - expect(() => { - CKDPriv('ed25519', xPrvTest, 1, password); - }).toThrow(new Error('Only hardened CKDPriv is supported for ed25519.')); +test('Normal CKDPriv is not supported for ed25519', async () => { + const xPrvTest = await createXPrvTestAsync(); + + await expect(CKDPriv('ed25519', xPrvTest, 1, password)).rejects.toThrow( + new Error('Only hardened CKDPriv is supported for ed25519.'), + ); }); test('CKDPub is not supported for ed25519', () => { @@ -627,33 +642,36 @@ test('CKDPub is not supported for ed25519', () => { }).toThrow(new Error('CKDPub is not supported for ed25519.')); }); -test('Normal encryption/decryption', () => { +test('Normal encryption/decryption', async () => { const data = Buffer.from('deadbeef', 'hex'); - expect(decrypt(password, encrypt(password, data))).toStrictEqual(data); + expect( + decrypt(password, await encryptAsync({ password, data })), + ).toStrictEqual(data); }); -test('Incorrect password', () => { - expect(() => { - decrypt(password + password, encrypt(password, Buffer.from(''))); - }).toThrow(IncorrectPassword); +test('Incorrect password', async () => { + const encrypted = await encryptAsync({ password, data: Buffer.from('') }); + expect(() => decrypt(password + password, encrypted)).toThrow( + IncorrectPassword, + ); }); -test('Incorrect mnemonic checksum', () => { - expect(() => { +test('Incorrect mnemonic checksum', async () => { + await expect( revealableSeedFromMnemonic( 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon', 'whatever password', - ); - }).toThrow(InvalidMnemonic); + ), + ).rejects.toThrow(InvalidMnemonic); }); -test('Incorrect mnemonic', () => { - expect(() => { +test('Incorrect mnemonic', async () => { + await expect( revealableSeedFromMnemonic( 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon', 'whatever password', - ); - }).toThrow(InvalidMnemonic); + ), + ).rejects.toThrow(InvalidMnemonic); }); test('sha256', () => { diff --git a/packages/core/src/secret/index.ts b/packages/core/src/secret/index.ts index 5ad8f33c992..ee9b4677882 100644 --- a/packages/core/src/secret/index.ts +++ b/packages/core/src/secret/index.ts @@ -15,8 +15,8 @@ import { import { ed25519, nistp256, secp256k1 } from './curves'; import { decrypt, - encrypt, - encryptString, + encryptAsync, + encryptStringAsync, ensureSensitiveTextEncoded, } from './encryptors/aes256'; import { hash160 } from './hash'; @@ -176,16 +176,20 @@ function decryptVerifyString({ ).toString(); } -function encryptVerifyString({ +async function encryptVerifyString({ password, addPrefixString = true, }: { password: string; addPrefixString?: boolean; -}) { +}): Promise { + const encrypted = await encryptAsync({ + password, + data: Buffer.from(DEFAULT_VERIFY_STRING), + }); return ( (addPrefixString ? EncryptPrefixVerifyString : '') + - encrypt(password, Buffer.from(DEFAULT_VERIFY_STRING)).toString('hex') + encrypted.toString('hex') ); } @@ -202,26 +206,22 @@ function decryptRevealableSeed({ return JSON.parse(rsJsonStr) as IBip39RevealableSeed; } -function encryptRevealableSeed({ +async function encryptRevealableSeed({ rs, password, }: { rs: IBip39RevealableSeed; password: string; -}): IBip39RevealableSeedEncryptHex { +}): Promise { if (!rs || !rs.entropyWithLangPrefixed || !rs.seed) { throw new Error('Invalid seed object'); } - return ( - EncryptPrefixHdCredential + - bufferUtils.bytesToHex( - encryptString({ - password, - data: JSON.stringify(rs), - dataEncoding: 'utf8', - }), - ) - ); + const encrypted = await encryptStringAsync({ + password, + data: JSON.stringify(rs), + dataEncoding: 'utf8', + }); + return EncryptPrefixHdCredential + bufferUtils.bytesToHex(encrypted); } function decryptImportedCredential({ @@ -232,43 +232,48 @@ function decryptImportedCredential({ password: string; }): ICoreImportedCredential { const text = bufferUtils.bytesToUtf8( - decrypt(password, credential.replace(EncryptPrefixImportedCredential, '')), + decrypt( + password, + typeof credential === 'string' + ? credential.replace(EncryptPrefixImportedCredential, '') + : credential, + ), ); return JSON.parse(text) as ICoreImportedCredential; } -function encryptImportedCredential({ +async function encryptImportedCredential({ credential, password, }: { credential: ICoreImportedCredential; password: string; -}): ICoreImportedCredentialEncryptHex { +}): Promise { if (!credential || !credential.privateKey) { throw new Error('Invalid credential object'); } - return ( - EncryptPrefixImportedCredential + - encryptString({ - password, - data: JSON.stringify(credential), - dataEncoding: 'utf8', - }) - ); + const encrypted = await encryptStringAsync({ + password, + data: JSON.stringify(credential), + dataEncoding: 'utf8', + }); + return EncryptPrefixImportedCredential + encrypted; } -function batchGetKeys( +async function batchGetKeys( curveName: ICurveName, hdCredential: ICoreHdCredentialEncryptHex, password: string, prefix: string, relPaths: Array, type: 'public' | 'private', -): Array<{ - path: string; - parentFingerPrint: Buffer; - extendedKey: IBip32ExtendedKey; -}> { +): Promise< + Array<{ + path: string; + parentFingerPrint: Buffer; + extendedKey: IBip32ExtendedKey; + }> +> { const ret: Array<{ path: string; parentFingerPrint: Buffer; @@ -307,12 +312,14 @@ function batchGetKeys( privkey: key, }; - relPaths.forEach((relPath) => { + // Process paths sequentially to maintain order and handle async operations + for (const relPath of relPaths) { const pathComponents = relPath.split('/'); let currentPath = prefix; let parent = cache[currentPath]; - pathComponents.forEach((pathComponent) => { + + for (const pathComponent of pathComponents) { currentPath = `${currentPath}/${pathComponent}`; if (typeof cache[currentPath] === 'undefined') { const index = pathComponent.endsWith("'") @@ -334,20 +341,25 @@ function batchGetKeys( }; } parent = cache[currentPath]; - }); + } + + const extendedKey = + type === 'private' + ? { + chainCode: cache[currentPath].privkey.chainCode, + key: await encryptAsync({ + password, + data: cache[currentPath].privkey.key, + }), + } + : deriver.N(cache[currentPath].privkey); ret.push({ path: currentPath, parentFingerPrint: cache[currentPath].parentFingerPrint, - extendedKey: - type === 'private' - ? { - chainCode: cache[currentPath].privkey.chainCode, - key: encrypt(password, cache[currentPath].privkey.key), - } - : deriver.N(cache[currentPath].privkey), + extendedKey, }); - }); + } return ret; } @@ -357,13 +369,13 @@ export type ISecretPrivateKeyInfo = { parentFingerPrint: Buffer; extendedKey: IBip32ExtendedKey; }; -function batchGetPrivateKeys( +async function batchGetPrivateKeys( curveName: ICurveName, hdCredential: ICoreHdCredentialEncryptHex, password: string, prefix: string, relPaths: Array, -): ISecretPrivateKeyInfo[] { +): Promise { return batchGetKeys( curveName, hdCredential, @@ -384,13 +396,13 @@ export type ISecretPublicKeyInfo = { parentFingerPrint: Buffer; extendedKey: IBip32ExtendedKey; }; -function batchGetPublicKeys( +async function batchGetPublicKeys( curveName: ICurveName, hdCredential: ICoreHdCredentialEncryptHex, password: string, prefix: string, relPaths: Array, -): ISecretPublicKeyInfo[] { +): Promise { return batchGetKeys( curveName, hdCredential, @@ -424,16 +436,20 @@ async function batchGetPublicKeysAsync( })); } const { curveName, hdCredential, password, prefix, relPaths } = params; - return Promise.resolve( - batchGetPublicKeys(curveName, hdCredential, password, prefix, relPaths), + return batchGetPublicKeys( + curveName, + hdCredential, + password, + prefix, + relPaths, ); } -function generateMasterKeyFromSeed( +async function generateMasterKeyFromSeed( curveName: ICurveName, hdCredential: IBip39RevealableSeedEncryptHex, password: string, -): IBip32ExtendedKey { +): Promise { const deriver: IBip32KeyDeriver = getDeriverByCurveName(curveName); const { seed } = decryptRevealableSeed({ rs: hdCredential, @@ -442,8 +458,12 @@ function generateMasterKeyFromSeed( const seedBuffer: Buffer = bufferUtils.toBuffer(seed); const masterKey: IBip32ExtendedKey = deriver.generateMasterKeyFromSeed(seedBuffer); + const encryptedKey = await encryptAsync({ + password, + data: masterKey.key, + }); return { - key: encrypt(password, masterKey.key), + key: encryptedKey, chainCode: masterKey.chainCode, }; } @@ -464,20 +484,24 @@ function N( return deriver.N(extPriv); } -function CKDPriv( +async function CKDPriv( curveName: ICurveName, encryptedParent: IBip32ExtendedKey, index: number, password: string, -): IBip32ExtendedKey { +): Promise { const deriver: IBip32KeyDeriver = getDeriverByCurveName(curveName); const parent: IBip32ExtendedKey = { key: decrypt(password, encryptedParent.key), chainCode: encryptedParent.chainCode, }; const child: IBip32ExtendedKey = deriver.CKDPriv(parent, index); + const encryptedKey = await encryptAsync({ + password, + data: child.key, + }); return { - key: encrypt(password, child.key), + key: encryptedKey, chainCode: child.chainCode, }; } @@ -490,11 +514,11 @@ function CKDPub( return getDeriverByCurveName(curveName).CKDPub(parent, index); } -function revealableSeedFromMnemonic( +async function revealableSeedFromMnemonic( mnemonic: string, password: string, passphrase?: string, -): IBip39RevealableSeedEncryptHex { +): Promise { const rs: IBip39RevealableSeed = mnemonicToRevealableSeed( mnemonic, passphrase, @@ -576,7 +600,7 @@ async function generateRootFingerprintHexAsync( ); } const { curveName, hdCredential, password } = params; - const masterKey = generateMasterKeyFromSeed( + const masterKey = await generateMasterKeyFromSeed( curveName, hdCredential, password, @@ -585,10 +609,10 @@ async function generateRootFingerprintHexAsync( return hash160(publicKey).slice(0, 4).toString('hex'); } -function revealableSeedFromTonMnemonic( +async function revealableSeedFromTonMnemonic( mnemonic: string, password: string, -): IBip39RevealableSeedEncryptHex { +): Promise { const rs: IBip39RevealableSeed = tonMnemonicToRevealableSeed(mnemonic); return encryptRevealableSeed({ rs, @@ -622,9 +646,6 @@ export { batchGetPublicKeysAsync, CKDPriv, CKDPub, - mnemonicToSeedAsync, - generateRootFingerprintHexAsync, - mnemonicFromEntropyAsync, compressPublicKey, decryptImportedCredential, decryptRevealableSeed, @@ -634,7 +655,10 @@ export { encryptVerifyString, fixV4VerifyStringToV5, generateMasterKeyFromSeed, + generateRootFingerprintHexAsync, mnemonicFromEntropy, + mnemonicFromEntropyAsync, + mnemonicToSeedAsync, N, publicFromPrivate, revealableSeedFromMnemonic, diff --git a/packages/kit-bg/src/dbs/local/LocalDbBase.ts b/packages/kit-bg/src/dbs/local/LocalDbBase.ts index 2a67e343be8..7998ec365d0 100644 --- a/packages/kit-bg/src/dbs/local/LocalDbBase.ts +++ b/packages/kit-bg/src/dbs/local/LocalDbBase.ts @@ -271,12 +271,11 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { return false; } try { - return ( - decryptVerifyString({ - password, - verifyString: context.verifyString, - }) === DEFAULT_VERIFY_STRING - ); + const decrypted = decryptVerifyString({ + password, + verifyString: context.verifyString, + }); + return decrypted === DEFAULT_VERIFY_STRING; } catch { return false; } @@ -290,9 +289,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { if (isValid) { return; } - if (!isValid) { - throw new WrongPassword(); - } + throw new WrongPassword(); } throw new PasswordNotSet(); } @@ -340,7 +337,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { tx, recordPairs: credentialsRecordPairs, name: ELocalDBStoreNames.Credential, - updater: (credential) => { + updater: async (credential) => { if (credential.id.startsWith('imported')) { // Ton mnemonic credential if (accountUtils.isTonMnemonicCredentialId(credential.id)) { @@ -348,7 +345,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { rs: credential.credential, password: oldPassword, }); - credential.credential = encryptRevealableSeed({ + credential.credential = await encryptRevealableSeed({ rs: revealableSeed, password: newPassword, }); @@ -358,7 +355,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { credential: credential.credential, password: oldPassword, }); - credential.credential = encryptImportedCredential({ + credential.credential = await encryptImportedCredential({ credential: importedCredential, password: newPassword, }); @@ -368,7 +365,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { rs: credential.credential, password: oldPassword, }); - credential.credential = encryptRevealableSeed({ + credential.credential = await encryptRevealableSeed({ rs: revealableSeed, password: newPassword, }); @@ -440,7 +437,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { // update context verifyString await this.txUpdateContextVerifyString({ tx, - verifyString: encryptVerifyString({ password: newPassword }), + verifyString: await encryptVerifyString({ password: newPassword }), }); }); } diff --git a/packages/kit-bg/src/dbs/local/realm/RealmDBAgent.ts b/packages/kit-bg/src/dbs/local/realm/RealmDBAgent.ts index 56d4ba3015d..05078a7ed69 100644 --- a/packages/kit-bg/src/dbs/local/realm/RealmDBAgent.ts +++ b/packages/kit-bg/src/dbs/local/realm/RealmDBAgent.ts @@ -229,8 +229,13 @@ export class RealmDBAgent extends LocalDbAgentBase implements ILocalDBAgent { const pairs = await this.buildRecordPairsFromIds(params); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await Promise.all(pairs.map(async (oldRecord) => updater(oldRecord[1]!))); + await Promise.all( + pairs.map(async (oldRecord) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const newRecord = await updater(oldRecord[1]!); + return newRecord; + }), + ); return Promise.resolve(undefined); } diff --git a/packages/kit-bg/src/migrations/v4ToV5Migration/V4MigrationForAccount.ts b/packages/kit-bg/src/migrations/v4ToV5Migration/V4MigrationForAccount.ts index a20e0d13e32..e9faa46139e 100644 --- a/packages/kit-bg/src/migrations/v4ToV5Migration/V4MigrationForAccount.ts +++ b/packages/kit-bg/src/migrations/v4ToV5Migration/V4MigrationForAccount.ts @@ -111,7 +111,7 @@ export class V4MigrationForAccount extends V4MigrationManagerBase { ); } const credentials: ICoreCredentialsInfo = { - imported: encryptImportedCredential({ + imported: await encryptImportedCredential({ credential: { privateKey, }, @@ -752,7 +752,7 @@ export class V4MigrationForAccount extends V4MigrationManagerBase { return this.decryptV4ImportedCredential({ v4dbCredential, encodedPassword: password - ? encodeSensitiveText({ text: password }) + ? await encodeSensitiveText({ text: password }) : await this.backgroundApi.serviceV4Migration.getMigrationPasswordV4(), }); } diff --git a/packages/kit-bg/src/migrations/v4ToV5Migration/v4local/V4LocalDbBase.ts b/packages/kit-bg/src/migrations/v4ToV5Migration/v4local/V4LocalDbBase.ts index b94c07de554..0519f2015d3 100644 --- a/packages/kit-bg/src/migrations/v4ToV5Migration/v4local/V4LocalDbBase.ts +++ b/packages/kit-bg/src/migrations/v4ToV5Migration/v4local/V4LocalDbBase.ts @@ -1,7 +1,7 @@ import { decrypt, decryptVerifyString, - encrypt, + encryptAsync, encryptVerifyString, ensureSensitiveTextEncoded, } from '@onekeyhq/core/src/secret'; @@ -152,7 +152,7 @@ export abstract class V4LocalDbBase extends V4LocalDbBaseContainer { // update context verifyString await this.txUpdateContextVerifyString({ tx, - verifyString: encryptVerifyString({ + verifyString: await encryptVerifyString({ password: newPassword, addPrefixString: false, }), @@ -184,7 +184,7 @@ export abstract class V4LocalDbBase extends V4LocalDbBaseContainer { tx, recordPairs: credentialsRecordPairs, name: EV4LocalDBStoreNames.Credential, - updater: (credential) => { + updater: async (credential) => { // imported credential if (credential.id.startsWith('imported')) { const importedCredential: IV4DBImportedCredentialRaw = JSON.parse( @@ -196,7 +196,10 @@ export abstract class V4LocalDbBase extends V4LocalDbBaseContainer { ); const importedCredentialRebuild: IV4DBImportedCredentialRaw = { privateKey: bufferUtils.bytesToHex( - encrypt(newPassword, privateKeyDecrypt), + await encryptAsync({ + password: newPassword, + data: privateKeyDecrypt, + }), ), }; @@ -211,9 +214,14 @@ export abstract class V4LocalDbBase extends V4LocalDbBaseContainer { const entropyDecrypt = decrypt(oldPassword, hdCredential.entropy); const hdCredentialRebuild: IV4DBHdCredentialRaw = { - seed: bufferUtils.bytesToHex(encrypt(newPassword, seedDecrypt)), + seed: bufferUtils.bytesToHex( + await encryptAsync({ password: newPassword, data: seedDecrypt }), + ), entropy: bufferUtils.bytesToHex( - encrypt(newPassword, entropyDecrypt), + await encryptAsync({ + password: newPassword, + data: entropyDecrypt, + }), ), }; @@ -231,7 +239,7 @@ export abstract class V4LocalDbBase extends V4LocalDbBaseContainer { }: { tx: IV4LocalDBTransaction; verifyString: string; - }) { + }): Promise { await this.txUpdateContext({ tx, updater: (record) => { diff --git a/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts b/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts index 547bf0067b6..b383801d84b 100644 --- a/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts +++ b/packages/kit-bg/src/services/ServiceAccount/ServiceAccount.ts @@ -1075,7 +1075,7 @@ class ServiceAccount extends ServiceBase { await this.backgroundApi.servicePassword.promptPasswordVerifyByWallet({ walletId, }); - const credentialEncrypt = encryptImportedCredential({ + const credentialEncrypt = await encryptImportedCredential({ credential: { privateKey: privateKeyDecoded, }, @@ -2121,7 +2121,7 @@ class ServiceAccount extends ServiceBase { let rs: IBip39RevealableSeedEncryptHex | undefined; try { - rs = revealableSeedFromMnemonic(realMnemonic, password); + rs = await revealableSeedFromMnemonic(realMnemonic, password); } catch { throw new InvalidMnemonic(); } @@ -2153,7 +2153,7 @@ class ServiceAccount extends ServiceBase { } let rs: IBip39RevealableSeedEncryptHex | undefined; try { - rs = revealableSeedFromTonMnemonic(realMnemonic, password); + rs = await revealableSeedFromTonMnemonic(realMnemonic, password); } catch { throw new InvalidMnemonic(); } diff --git a/packages/kit-bg/src/services/ServiceAddressBook.ts b/packages/kit-bg/src/services/ServiceAddressBook.ts index 813e7f6ed6c..fc244c8dabc 100644 --- a/packages/kit-bg/src/services/ServiceAddressBook.ts +++ b/packages/kit-bg/src/services/ServiceAddressBook.ts @@ -149,7 +149,7 @@ class ServiceAddressBook extends ServiceBase { const items = await this.getItems(); await this.setItems( items, - encodeSensitiveText({ text: String(Date.now()) }), + await encodeSensitiveText({ text: String(Date.now()) }), ); } } diff --git a/packages/kit-bg/src/services/ServiceCloudBackup/index.ts b/packages/kit-bg/src/services/ServiceCloudBackup/index.ts index ed7197b2773..209be131843 100644 --- a/packages/kit-bg/src/services/ServiceCloudBackup/index.ts +++ b/packages/kit-bg/src/services/ServiceCloudBackup/index.ts @@ -6,7 +6,10 @@ import { encryptImportedCredential, encryptRevealableSeed, } from '@onekeyhq/core/src/secret'; -import { decrypt, encrypt } from '@onekeyhq/core/src/secret/encryptors/aes256'; +import { + decrypt, + encryptAsync, +} from '@onekeyhq/core/src/secret/encryptors/aes256'; import type { IDBWallet } from '@onekeyhq/kit-bg/src/dbs/local/types'; import { cloudBackupPersistAtom } from '@onekeyhq/kit-bg/src/states/jotai/atoms'; import { @@ -185,9 +188,11 @@ class ServiceCloudBackup extends ServiceBase { return { privateData: password - ? encrypt( - password, - Buffer.from(JSON.stringify(privateBackupData), 'utf8'), + ? ( + await encryptAsync({ + password, + data: Buffer.from(JSON.stringify(privateBackupData), 'utf8'), + }) ).toString('base64') : '', publicData: publicBackupData, @@ -369,24 +374,26 @@ class ServiceCloudBackup extends ServiceBase { privateData: IPrivateBackupData; remotePassword: string; }) { - Object.keys(privateData.credentials).forEach((key) => { - const credential = privateData.credentials[key]; - try { - const credentialRs = JSON.parse(credential) as { - entropy: string; - seed: string; - }; - privateData.credentials[key] = encryptRevealableSeed({ - rs: { - entropyWithLangPrefixed: credentialRs.entropy, - seed: credentialRs.seed, - }, - password: remotePassword, - }); - } catch { - // - } - }); + await Promise.all( + Object.keys(privateData.credentials).map(async (key) => { + const credential = privateData.credentials[key]; + try { + const credentialRs = JSON.parse(credential) as { + entropy: string; + seed: string; + }; + privateData.credentials[key] = await encryptRevealableSeed({ + rs: { + entropyWithLangPrefixed: credentialRs.entropy, + seed: credentialRs.seed, + }, + password: remotePassword, + }); + } catch { + // + } + }), + ); return privateData; } @@ -551,7 +558,7 @@ class ServiceCloudBackup extends ServiceBase { password: remotePassword, credential: privateData.credentials[id], }); - const rsEncoded = encryptRevealableSeed({ + const rsEncoded = await encryptRevealableSeed({ rs: rsDecoded, password: localPassword, }); @@ -587,7 +594,7 @@ class ServiceCloudBackup extends ServiceBase { if (version !== IMPORTED_ACCOUNT_BACKUP_VERSION) { return; } - const importedCredential = encryptImportedCredential({ + const importedCredential = await encryptImportedCredential({ credential: decryptImportedCredential({ credential: privateData.credentials[account.id], password: remotePassword, diff --git a/packages/kit-bg/src/services/ServicePassword/biologyAuthUtils.ts b/packages/kit-bg/src/services/ServicePassword/biologyAuthUtils.ts index 3a14ed46b23..fc42f7a1e98 100644 --- a/packages/kit-bg/src/services/ServicePassword/biologyAuthUtils.ts +++ b/packages/kit-bg/src/services/ServicePassword/biologyAuthUtils.ts @@ -26,7 +26,7 @@ class BiologyAuthUtils implements IBiologyAuth { if (!secureStorageInstance.supportSecureStorage()) return; let text = decodeSensitiveText({ encodedText: password }); const settings = await settingsPersistAtom.get(); - text = encodeSensitiveText({ + text = await encodeSensitiveText({ text, key: `${encodeKeyPrefix}${settings.sensitiveEncodeKey}`, }); @@ -44,7 +44,7 @@ class BiologyAuthUtils implements IBiologyAuth { encodedText: text, key: `${encodeKeyPrefix}${settings.sensitiveEncodeKey}`, }); - text = encodeSensitiveText({ text }); + text = await encodeSensitiveText({ text }); return text; } throw new Error('No password'); diff --git a/packages/kit-bg/src/services/ServicePassword/index.ts b/packages/kit-bg/src/services/ServicePassword/index.ts index ace60dc3b38..c9339dd1fd8 100644 --- a/packages/kit-bg/src/services/ServicePassword/index.ts +++ b/packages/kit-bg/src/services/ServicePassword/index.ts @@ -9,7 +9,7 @@ import { decrypt, decryptString, encodeSensitiveText, - encryptString, + encryptStringAsync, ensureSensitiveTextEncoded, getBgSensitiveTextEncodeKey, revealEntropyToMnemonic, @@ -114,7 +114,7 @@ export default class ServicePassword extends ServiceBase { @backgroundMethod() async encryptString(params: IEncryptStringParams) { - return encryptString(params); + return encryptStringAsync(params); } @backgroundMethod() @@ -125,7 +125,7 @@ export default class ServicePassword extends ServiceBase { @backgroundMethod() async encryptByInstanceId(input: string): Promise { const instanceId = await this.backgroundApi.serviceSetting.getInstanceId(); - const output = encodeSensitiveText({ + const output = await encodeSensitiveText({ text: input, key: instanceId, }); diff --git a/packages/kit-bg/src/vaults/base/VaultBase.ts b/packages/kit-bg/src/vaults/base/VaultBase.ts index 99a729332cd..014dae37b5c 100644 --- a/packages/kit-bg/src/vaults/base/VaultBase.ts +++ b/packages/kit-bg/src/vaults/base/VaultBase.ts @@ -268,7 +268,7 @@ export abstract class VaultBaseChainOnly extends VaultContext { ): Promise { const input = decodeSensitiveText({ encodedText: params.input }); let privateKey = hexUtils.stripHexPrefix(input); - privateKey = encodeSensitiveText({ text: privateKey }); + privateKey = await encodeSensitiveText({ text: privateKey }); return { privateKey, }; diff --git a/packages/kit-bg/src/vaults/impls/ada/Vault.ts b/packages/kit-bg/src/vaults/impls/ada/Vault.ts index 815e57a37a9..2cf5c00a972 100644 --- a/packages/kit-bg/src/vaults/impls/ada/Vault.ts +++ b/packages/kit-bg/src/vaults/impls/ada/Vault.ts @@ -380,12 +380,12 @@ export default class Vault extends VaultBase { }); } - override getPrivateKeyFromImported( + override async getPrivateKeyFromImported( params: IGetPrivateKeyFromImportedParams, ): Promise { const input = decodeSensitiveText({ encodedText: params.input }); let privateKey = bufferUtils.bytesToHex(decodePrivateKeyByXprv(input)); - privateKey = encodeSensitiveText({ text: privateKey }); + privateKey = await encodeSensitiveText({ text: privateKey }); return Promise.resolve({ privateKey }); } diff --git a/packages/kit-bg/src/vaults/impls/algo/Vault.ts b/packages/kit-bg/src/vaults/impls/algo/Vault.ts index 316bef007b9..07945a4f707 100644 --- a/packages/kit-bg/src/vaults/impls/algo/Vault.ts +++ b/packages/kit-bg/src/vaults/impls/algo/Vault.ts @@ -522,14 +522,14 @@ export default class Vault extends VaultBase { }); } - override getPrivateKeyFromImported( + override async getPrivateKeyFromImported( params: IGetPrivateKeyFromImportedParams, ): Promise { const input = decodeSensitiveText({ encodedText: params.input }); let privateKey = Buffer.from(sdkAlgo.seedFromMnemonic(input)).toString( 'hex', ); - privateKey = encodeSensitiveText({ text: privateKey }); + privateKey = await encodeSensitiveText({ text: privateKey }); return Promise.resolve({ privateKey, }); diff --git a/packages/kit-bg/src/vaults/impls/btc/Vault.ts b/packages/kit-bg/src/vaults/impls/btc/Vault.ts index 9a135be45b5..0bd1649b2a8 100644 --- a/packages/kit-bg/src/vaults/impls/btc/Vault.ts +++ b/packages/kit-bg/src/vaults/impls/btc/Vault.ts @@ -1286,7 +1286,7 @@ export default class VaultBtc extends VaultBase { return { btcExtraInfo, account: signerAccount, relPaths }; } - override getPrivateKeyFromImported(params: { + override async getPrivateKeyFromImported(params: { input: string; }): Promise<{ privateKey: string }> { // params.input is xprvt format: @@ -1295,7 +1295,7 @@ export default class VaultBtc extends VaultBase { // result is hex format: let privateKey = convertBtcXprvtToHex({ xprvt: input }); - privateKey = encodeSensitiveText({ text: privateKey }); + privateKey = await encodeSensitiveText({ text: privateKey }); return Promise.resolve({ privateKey, }); diff --git a/packages/kit-bg/src/vaults/impls/fil/Vault.ts b/packages/kit-bg/src/vaults/impls/fil/Vault.ts index ade2e53690d..be65b5d4e9a 100644 --- a/packages/kit-bg/src/vaults/impls/fil/Vault.ts +++ b/packages/kit-bg/src/vaults/impls/fil/Vault.ts @@ -406,7 +406,7 @@ export default class Vault extends VaultBase { }); } - override getPrivateKeyFromImported( + override async getPrivateKeyFromImported( params: IGetPrivateKeyFromImportedParams, ): Promise { let credential = decodeSensitiveText({ encodedText: params.input }); @@ -430,7 +430,7 @@ export default class Vault extends VaultBase { privateKey = Buffer.from(credential, 'hex'); } - privateKey = encodeSensitiveText({ + privateKey = await encodeSensitiveText({ text: privateKey?.toString('hex') ?? '', }); diff --git a/packages/kit-bg/src/vaults/impls/kaspa/Vault.ts b/packages/kit-bg/src/vaults/impls/kaspa/Vault.ts index 413e8a23d85..100f05dac33 100644 --- a/packages/kit-bg/src/vaults/impls/kaspa/Vault.ts +++ b/packages/kit-bg/src/vaults/impls/kaspa/Vault.ts @@ -355,13 +355,13 @@ export default class Vault extends VaultBase { throw new NotImplemented(); } - override getPrivateKeyFromImported( + override async getPrivateKeyFromImported( params: IGetPrivateKeyFromImportedParams, ): Promise { const input = decodeSensitiveText({ encodedText: params.input }); if (this.isHexPrivateKey(input)) { let privateKey = input.startsWith('0x') ? input.slice(2) : input; - privateKey = encodeSensitiveText({ text: privateKey }); + privateKey = await encodeSensitiveText({ text: privateKey }); return Promise.resolve({ privateKey, }); @@ -369,7 +369,7 @@ export default class Vault extends VaultBase { if (this.isWIFPrivateKey(input)) { const privateKeyBuffer = privateKeyFromWIF(input); - const wifPrivateKey = encodeSensitiveText({ + const wifPrivateKey = await encodeSensitiveText({ text: privateKeyBuffer.toString(), }); return Promise.resolve({ diff --git a/packages/kit-bg/src/vaults/impls/near/Vault.ts b/packages/kit-bg/src/vaults/impls/near/Vault.ts index bd6aa63017c..11a5991e39c 100644 --- a/packages/kit-bg/src/vaults/impls/near/Vault.ts +++ b/packages/kit-bg/src/vaults/impls/near/Vault.ts @@ -487,7 +487,7 @@ export default class Vault extends VaultBase { }); } - override getPrivateKeyFromImported( + override async getPrivateKeyFromImported( params: IGetPrivateKeyFromImportedParams, ): Promise { let privateKey = ''; @@ -499,7 +499,7 @@ export default class Vault extends VaultBase { if (prefix === 'ed25519' && decodedPrivateKey.length === 64) { privateKey = decodedPrivateKey.slice(0, 32).toString('hex'); } - privateKey = encodeSensitiveText({ text: privateKey }); + privateKey = await encodeSensitiveText({ text: privateKey }); return Promise.resolve({ privateKey, diff --git a/packages/kit-bg/src/vaults/impls/sol/Vault.ts b/packages/kit-bg/src/vaults/impls/sol/Vault.ts index 39867a6f99b..552e3f99250 100644 --- a/packages/kit-bg/src/vaults/impls/sol/Vault.ts +++ b/packages/kit-bg/src/vaults/impls/sol/Vault.ts @@ -1274,7 +1274,7 @@ export default class Vault extends VaultBase { privateKey = decodedPrivateKey.slice(0, 32).toString('hex'); } - privateKey = encodeSensitiveText({ text: privateKey ?? '' }); + privateKey = await encodeSensitiveText({ text: privateKey ?? '' }); return { privateKey, }; diff --git a/packages/kit-bg/src/vaults/impls/xrp/Vault.ts b/packages/kit-bg/src/vaults/impls/xrp/Vault.ts index dc91af5c438..b2d0f815dc6 100644 --- a/packages/kit-bg/src/vaults/impls/xrp/Vault.ts +++ b/packages/kit-bg/src/vaults/impls/xrp/Vault.ts @@ -294,12 +294,12 @@ export default class Vault extends VaultBase { }); } - override getPrivateKeyFromImported( + override async getPrivateKeyFromImported( params: IGetPrivateKeyFromImportedParams, ): Promise { const input = decodeSensitiveText({ encodedText: params.input }); let privateKey = bufferUtils.bytesToHex(input); - privateKey = encodeSensitiveText({ text: privateKey }); + privateKey = await encodeSensitiveText({ text: privateKey }); return Promise.resolve({ privateKey }); }