diff --git a/development/webpackTools.js b/development/webpackTools.js index f3fa0b446b7..c801f47abc1 100644 --- a/development/webpackTools.js +++ b/development/webpackTools.js @@ -335,7 +335,9 @@ function normalizeConfig({ config.resolve.fallback = { ...config.resolve.fallback, - 'crypto': require.resolve('crypto-browserify'), + 'crypto': require.resolve( + '@onekeyhq/shared/src/modules3rdParty/cross-crypto/index.js', + ), 'stream': require.resolve('stream-browserify'), 'path': false, 'https': false, diff --git a/packages/app/metro.config.js b/packages/app/metro.config.js index a5ac76e907a..f02893eb3ac 100644 --- a/packages/app/metro.config.js +++ b/packages/app/metro.config.js @@ -25,7 +25,9 @@ config.resolver.extraNodeModules = { fs: require.resolve('react-native-level-fs'), path: require.resolve('path-browserify'), stream: require.resolve('readable-stream'), - crypto: require.resolve('react-native-crypto'), + 'crypto': require.resolve( + '@onekeyhq/shared/src/modules3rdParty/cross-crypto/index.native.js', + ), http: require.resolve('stream-http'), https: require.resolve('https-browserify'), net: require.resolve('react-native-tcp-socket'), diff --git a/packages/engine/package.json b/packages/engine/package.json index 92ab72b9c68..51fd5c194a8 100644 --- a/packages/engine/package.json +++ b/packages/engine/package.json @@ -51,7 +51,7 @@ "bech32": "^2.0.0", "bignumber.js": "^9.0.1", "bip32": "^4.0.0", - "bip39": "^3.0.4", + "bip39": "^3.1.0", "bitcoinforkjs": "git+https://github.com/OneKeyHQ/bitcoinjs-lib.git#feat/remove-npm-lock", "bitcoinjs-message": "^2.2.0", "bs58check": "^2.1.2", diff --git a/packages/engine/src/index.ts b/packages/engine/src/index.ts index b35dbf6e370..92931aa0cf7 100644 --- a/packages/engine/src/index.ts +++ b/packages/engine/src/index.ts @@ -206,7 +206,7 @@ class Engine { @backgroundMethod() generateMnemonic(): Promise { - return Promise.resolve(bip39.generateMnemonic()); + return Promise.resolve(bip39.generateMnemonic(256)); } @backgroundMethod() @@ -372,7 +372,7 @@ class Engine { await this.validator.validatePasswordStrength(password); const [usedMnemonic] = await Promise.all([ - this.validator.validateMnemonic(mnemonic || bip39.generateMnemonic()), + this.validator.validateMnemonic(mnemonic || bip39.generateMnemonic(256)), this.validator.validateHDWalletNumber(), ]); diff --git a/packages/engine/src/secret/index.test.ts b/packages/engine/src/secret/index.test.ts index a3f781ec1f4..3f8efff0926 100644 --- a/packages/engine/src/secret/index.test.ts +++ b/packages/engine/src/secret/index.test.ts @@ -781,7 +781,7 @@ test('Basic mnemonic & seed tests', () => { }); test('Mnemonic generation', () => { - const mnemonic = bip39.generateMnemonic(); + const mnemonic = bip39.generateMnemonic(256); const rs = revealableSeedFromMnemonic(mnemonic, password); expect( mnemonicFromEntropy(rs.entropyWithLangPrefixed, password), diff --git a/packages/ext/development/nextWebpack.js b/packages/ext/development/nextWebpack.js index f1ad51c99e2..60371859681 100644 --- a/packages/ext/development/nextWebpack.js +++ b/packages/ext/development/nextWebpack.js @@ -24,7 +24,9 @@ function nextWebpack( config.resolve = config.resolve || {}; config.resolve.fallback = { ...config.resolve.fallback, - 'crypto': require.resolve('crypto-browserify'), + 'crypto': require.resolve( + '@onekeyhq/shared/src/modules3rdParty/cross-crypto/index.js', + ), 'stream': require.resolve('stream-browserify'), 'path': false, 'https': false, diff --git a/packages/kit-bg/src/BackgroundApi.ts b/packages/kit-bg/src/BackgroundApi.ts index cbc9bb61733..d0861e16c8b 100644 --- a/packages/kit-bg/src/BackgroundApi.ts +++ b/packages/kit-bg/src/BackgroundApi.ts @@ -1,5 +1,7 @@ /* eslint-disable new-cap */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ + +// eslint-disable-next-line import/order import { Engine } from '@onekeyhq/engine'; import BackgroundApiBase from './BackgroundApiBase'; diff --git a/packages/shared/src/modules3rdParty/cross-crypto/index.js b/packages/shared/src/modules3rdParty/cross-crypto/index.js new file mode 100644 index 00000000000..e8d35df92fd --- /dev/null +++ b/packages/shared/src/modules3rdParty/cross-crypto/index.js @@ -0,0 +1,23 @@ +if (process.env.NODE_ENV !== 'production') { + const getRandomValuesOld = global.crypto.getRandomValues; + global.crypto.getRandomValues = function (...args) { + console.log('------------ call global.crypto.getRandomValues (web)'); + return getRandomValuesOld.apply(global.crypto, args); + }; +} + +const crypto = require('crypto-browserify'); + +if (global.crypto) { + global.crypto.randomBytes = global.crypto.randomBytes || crypto.randomBytes; + crypto.getRandomValues = + crypto.getRandomValues || global.crypto.getRandomValues; +} +crypto.$$isOneKeyShim = true; +global.crypto.$$isOneKeyShim = true; + +if (process.env.NODE_ENV !== 'production') { + console.log('crypto-browserify polyfilled', crypto, global.crypto); +} + +module.exports = crypto; diff --git a/packages/shared/src/modules3rdParty/cross-crypto/index.native.js b/packages/shared/src/modules3rdParty/cross-crypto/index.native.js new file mode 100644 index 00000000000..d9c046f238d --- /dev/null +++ b/packages/shared/src/modules3rdParty/cross-crypto/index.native.js @@ -0,0 +1,37 @@ +// react-native-crypto +// react-native-quick-crypto +// react-native-get-random-values +// react-native-randombytes (deprecated) + +if (global.crypto && global.crypto.getRandomValues) { + delete global.crypto.getRandomValues; +} +// shim global.crypto.getRandomValues +require('react-native-get-random-values'); + +if (process.env.NODE_ENV !== 'production') { + const getRandomValuesOld = global.crypto.getRandomValues; + global.crypto.getRandomValues = function (...args) { + console.log('------------ call global.crypto.getRandomValues (native)'); + return getRandomValuesOld.apply(global.crypto, args); + }; +} + +const crypto = require('react-native-crypto'); + +const { randomBytes } = require('@noble/hashes/utils'); + +// re-assign randomBytes from global.crypto.getRandomValues +crypto.randomBytes = randomBytes; +crypto.getRandomValues = + crypto.getRandomValues || global.crypto.getRandomValues; +global.crypto.randomBytes = global.crypto.randomBytes || crypto.randomBytes; + +crypto.$$isOneKeyShim = true; +global.crypto.$$isOneKeyShim = true; + +if (process.env.NODE_ENV !== 'production') { + console.log('react-native-crypto polyfilled', crypto, global.crypto); +} + +module.exports = crypto; diff --git a/packages/shared/src/modules3rdParty/cross-crypto/verify.ts b/packages/shared/src/modules3rdParty/cross-crypto/verify.ts new file mode 100644 index 00000000000..9500c10b183 --- /dev/null +++ b/packages/shared/src/modules3rdParty/cross-crypto/verify.ts @@ -0,0 +1,28 @@ +import assert from 'assert'; +import * as crypto from 'crypto'; + +const globalCrypto = global.crypto; + +// @ts-ignore +assert.ok(globalCrypto?.$$isOneKeyShim, 'global crypto is not polyfilled'); +// @ts-ignore +assert.ok(crypto?.$$isOneKeyShim, 'crypto is not polyfilled'); + +assert.equal( + // eslint-disable-next-line @typescript-eslint/unbound-method + globalCrypto.getRandomValues, + // @ts-ignore + crypto.getRandomValues, + 'getRandomValues is not matched', +); + +assert.equal( + // @ts-ignore + globalCrypto.randomBytes, + crypto.randomBytes, + 'randomBytes is not matched', +); + +if (process.env.NODE_ENV !== 'production') { + console.log('cross-crypto verify success!'); +} diff --git a/packages/shared/src/polyfills/index.ts b/packages/shared/src/polyfills/index.ts index 33ad1d7fc97..75f9d1dbaf1 100644 --- a/packages/shared/src/polyfills/index.ts +++ b/packages/shared/src/polyfills/index.ts @@ -1,6 +1,9 @@ -// eslint-disable-next-line import/order +/* eslint-disable import/order */ import './polyfillsPlatform'; +// eslint-disable-next-line import/order +import '../modules3rdParty/cross-crypto/verify'; + import { normalizeRequestLibs } from '../request/normalize'; import timerUtils from '../utils/timerUtils'; diff --git a/packages/shared/src/utils/assertUtils.ts b/packages/shared/src/utils/assertUtils.ts index 2b2e973242f..e70c0b54517 100644 --- a/packages/shared/src/utils/assertUtils.ts +++ b/packages/shared/src/utils/assertUtils.ts @@ -1,3 +1,5 @@ +import assert from 'assert'; + type ErrorType = undefined | string | Error; const check = (statement: any, orError?: ErrorType) => { @@ -25,4 +27,4 @@ const checkIsUndefined = (something: any, orError?: ErrorType) => { ); }; -export { check, checkIsDefined, checkIsUndefined }; +export { assert, check, checkIsDefined, checkIsUndefined }; diff --git a/yarn.lock b/yarn.lock index ddbc10691b3..ebb00fa72d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6597,7 +6597,7 @@ __metadata: bech32: ^2.0.0 bignumber.js: ^9.0.1 bip32: ^4.0.0 - bip39: ^3.0.4 + bip39: ^3.1.0 bitcoinforkjs: "git+https://github.com/OneKeyHQ/bitcoinjs-lib.git#feat/remove-npm-lock" bitcoinjs-message: ^2.2.0 bs58check: ^2.1.2 @@ -13288,6 +13288,15 @@ __metadata: languageName: node linkType: hard +"bip39@npm:^3.1.0": + version: 3.1.0 + resolution: "bip39@npm:3.1.0" + dependencies: + "@noble/hashes": ^1.2.0 + checksum: 1224e763ffc6b097052ed8abd57f0e521ad6d31f1645be0d0a15f4417c13f8461f00e47e9cf7c8c784bd533f4fb1ee3ab020f258c7df45ee5dc722b4b0336cfc + languageName: node + linkType: hard + "bip66@npm:^1.1.0, bip66@npm:^1.1.5": version: 1.1.5 resolution: "bip66@npm:1.1.5"