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/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..31ac8d2ee59 --- /dev/null +++ b/packages/core/src/secret/encryptors/__tests__/aes256.test.ts @@ -0,0 +1,135 @@ +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, + }); + 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 82c8b441fd8..d2f514d3c20 100644 --- a/packages/core/src/secret/index.ts +++ b/packages/core/src/secret/index.ts @@ -13,8 +13,8 @@ import { import { ed25519, nistp256, secp256k1 } from './curves'; import { decrypt, - encrypt, - encryptString, + encryptAsync, + encryptStringAsync, ensureSensitiveTextEncoded, } from './encryptors/aes256'; import { hash160 } from './hash'; @@ -174,16 +174,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') ); } @@ -200,23 +204,19 @@ function decryptRevealableSeed({ return JSON.parse(rsJsonStr) as IBip39RevealableSeed; } -function encryptRevealableSeed({ +async function encryptRevealableSeed({ rs, password, }: { rs: IBip39RevealableSeed; password: string; -}): IBip39RevealableSeedEncryptHex { - return ( - EncryptPrefixHdCredential + - bufferUtils.bytesToHex( - encryptString({ - password, - data: JSON.stringify(rs), - dataEncoding: 'utf8', - }), - ) - ); +}): Promise { + const encrypted = await encryptStringAsync({ + password, + data: JSON.stringify(rs), + dataEncoding: 'utf8', + }); + return EncryptPrefixHdCredential + bufferUtils.bytesToHex(encrypted); } function decryptImportedCredential({ @@ -227,40 +227,45 @@ 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 { - return ( - EncryptPrefixImportedCredential + - encryptString({ - password, - data: JSON.stringify(credential), - dataEncoding: 'utf8', - }) - ); +}): Promise { + 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; @@ -299,12 +304,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("'") @@ -326,20 +333,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; } @@ -349,13 +361,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, @@ -376,13 +388,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, @@ -416,16 +428,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, @@ -434,8 +450,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, }; } @@ -456,20 +476,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, }; } @@ -482,11 +506,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, @@ -521,7 +545,7 @@ export type IMnemonicFromEntropyAsyncParams = { hdCredential: IBip39RevealableSeedEncryptHex; password: string; }; -export function mnemonicFromEntropyAsync( +async function mnemonicFromEntropyAsync( params: IMnemonicFromEntropyAsyncParams, ): Promise { if (platformEnv.isNative) { @@ -536,7 +560,7 @@ export type IMnemonicToSeedAsyncParams = { mnemonic: string; passphrase?: string; }; -export async function mnemonicToSeedAsync( +async function mnemonicToSeedAsync( params: IMnemonicToSeedAsyncParams, ): Promise { if (platformEnv.isNative) { @@ -555,7 +579,7 @@ export type IGenerateRootFingerprintHexAsyncParams = { hdCredential: IBip39RevealableSeedEncryptHex; password: string; }; -export async function generateRootFingerprintHexAsync( +async function generateRootFingerprintHexAsync( params: IGenerateRootFingerprintHexAsyncParams, ): Promise { if (platformEnv.isNative) { @@ -564,7 +588,7 @@ export async function generateRootFingerprintHexAsync( ); } const { curveName, hdCredential, password } = params; - const masterKey = generateMasterKeyFromSeed( + const masterKey = await generateMasterKeyFromSeed( curveName, hdCredential, password, @@ -573,10 +597,10 @@ export 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, @@ -624,6 +648,9 @@ export { publicFromPrivate, revealableSeedFromMnemonic, revealableSeedFromTonMnemonic, + mnemonicFromEntropyAsync, + mnemonicToSeedAsync, + generateRootFingerprintHexAsync, tonMnemonicFromEntropy, sign, uncompressPublicKey, diff --git a/packages/kit-bg/src/dbs/local/LocalDbBase.ts b/packages/kit-bg/src/dbs/local/LocalDbBase.ts index 7290af34e03..e7e8650fe0b 100644 --- a/packages/kit-bg/src/dbs/local/LocalDbBase.ts +++ b/packages/kit-bg/src/dbs/local/LocalDbBase.ts @@ -272,12 +272,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; } @@ -291,9 +290,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { if (isValid) { return; } - if (!isValid) { - throw new WrongPassword(); - } + throw new WrongPassword(); } throw new PasswordNotSet(); } @@ -341,7 +338,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)) { @@ -349,7 +346,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { rs: credential.credential, password: oldPassword, }); - credential.credential = encryptRevealableSeed({ + credential.credential = await encryptRevealableSeed({ rs: revealableSeed, password: newPassword, }); @@ -359,7 +356,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { credential: credential.credential, password: oldPassword, }); - credential.credential = encryptImportedCredential({ + credential.credential = await encryptImportedCredential({ credential: importedCredential, password: newPassword, }); @@ -369,7 +366,7 @@ export abstract class LocalDbBase extends LocalDbBaseContainer { rs: credential.credential, password: oldPassword, }); - credential.credential = encryptRevealableSeed({ + credential.credential = await encryptRevealableSeed({ rs: revealableSeed, password: newPassword, }); @@ -441,7 +438,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 49ccb04252f..77d22041d80 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, }, @@ -2078,7 +2078,7 @@ class ServiceAccount extends ServiceBase { let rs: IBip39RevealableSeedEncryptHex | undefined; try { - rs = revealableSeedFromMnemonic(realMnemonic, password); + rs = await revealableSeedFromMnemonic(realMnemonic, password); } catch { throw new InvalidMnemonic(); } @@ -2110,7 +2110,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 0ce4c387ebd..b31ea06a4b4 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, @@ -108,7 +108,7 @@ export default class ServicePassword extends ServiceBase { @backgroundMethod() async encryptString(params: IEncryptStringParams) { - return encryptString(params); + return encryptStringAsync(params); } @backgroundMethod() @@ -119,7 +119,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 3f4a74038a8..a9dcf9baf60 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 b515859e22c..40965b626f1 100644 --- a/packages/kit-bg/src/vaults/impls/btc/Vault.ts +++ b/packages/kit-bg/src/vaults/impls/btc/Vault.ts @@ -1282,7 +1282,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: @@ -1291,7 +1291,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 8e048c5035f..0b3fc8d54bc 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 }); } diff --git a/packages/shared/src/utils/debug/debugUtils.ts b/packages/shared/src/utils/debug/debugUtils.ts index 733de4419dd..68d35dce3f5 100644 --- a/packages/shared/src/utils/debug/debugUtils.ts +++ b/packages/shared/src/utils/debug/debugUtils.ts @@ -19,10 +19,12 @@ export function useDebugComponentRemountLog({ useEffect(() => { if (process.env.NODE_ENV !== 'production') { - console.log( + console.groupCollapsed( `@@ComponentRemountLog mounted: ${nameRef.current}`, - stringUtils.safeStringify(payloadRef.current), ); + console.log(stringUtils.safeStringify(payloadRef.current)); + console.log('href: ', globalThis?.location?.href); + console.groupEnd(); } return () => { if (process.env.NODE_ENV !== 'production') {