diff --git a/packages/keyring/src/index.spec.ts b/packages/keyring/src/index.spec.ts index 5a9516020d..8f6df0dc2f 100644 --- a/packages/keyring/src/index.spec.ts +++ b/packages/keyring/src/index.spec.ts @@ -358,7 +358,7 @@ describe('keypair', (): void => { }); it('creates with dev phrase with derivation path specified', (): void => { - const pair = keyring.createFromUri(PHRASE, undefined, undefined, undefined, 2048); + const pair = keyring.createFromUri(PHRASE); expect( pair.address @@ -367,7 +367,7 @@ describe('keypair', (): void => { it('creates with dev phrase with derivation path specified - addFromUri', (): void => { expect( - keyring.addFromUri(PHRASE, undefined, undefined, undefined, 2048).address + keyring.addFromUri(PHRASE).address ).toEqual(ETH_ADDRESS_ONE); }); @@ -375,12 +375,12 @@ describe('keypair', (): void => { const keyringUntyped = new Keyring(); expect( - keyringUntyped.addFromUri(PHRASE, {}, 'ethereum', undefined, 2048).address + keyringUntyped.addFromUri(PHRASE, {}, 'ethereum').address ).toEqual(ETH_ADDRESS_ONE); }); it('encodes a pair toJSON (and decodes)', (): void => { - const pair = keyring.createFromUri(PHRASE, undefined, undefined, undefined, 2048); + const pair = keyring.createFromUri(PHRASE); const json = pair.toJson('password'); expect(json.address).toEqual('0x0381351b1b46d2602b0992bb5d5531f9c1696b0812feb2534b6884adc47e2e1d8b'); // this is the public key (different from address for ethereum) @@ -399,7 +399,7 @@ describe('keypair', (): void => { }); it('encodes a pair toJSON and back', (): void => { - const pairOriginal = keyring.createFromUri(PHRASE, undefined, undefined, undefined, 2048); + const pairOriginal = keyring.createFromUri(PHRASE); const json = pairOriginal.toJson('password'); const pair = keyring.addFromJson( json diff --git a/packages/keyring/src/keyring.ts b/packages/keyring/src/keyring.ts index 4e47ca2503..452347a5ba 100644 --- a/packages/keyring/src/keyring.ts +++ b/packages/keyring/src/keyring.ts @@ -152,15 +152,10 @@ export class Keyring implements KeyringInstance { * @name addFromUri * @summary Creates an account via an suri * @description Extracts the phrase, path and password from a SURI format for specifying secret keys `//////` (the `///password` may be omitted, and `/` and `//` maybe repeated and mixed). The secret can be a hex string, mnemonic phrase or a string (to be padded) - * @param _suri - * @param meta - * @param type The supported types of pairs. Either 'ed25519' | 'sr25519' | 'ecdsa' | 'ethereum'. - * @param wordlist - Optional custom wordlist for mnemonic. - * @param rounds - Optional: Number of PBKDF2 iterations to run (default: 210000 (when onlyJS = true) or 2048 (when onlyJS = false). - */ - public addFromUri (suri: string, meta: KeyringPair$Meta = {}, type: KeypairType = this.type, wordlist?: string[], rounds?: number): KeyringPair { + */ + public addFromUri (suri: string, meta: KeyringPair$Meta = {}, type: KeypairType = this.type, wordlist?: string[]): KeyringPair { return this.addPair( - this.createFromUri(suri, meta, type, wordlist, rounds) + this.createFromUri(suri, meta, type, wordlist) ); } @@ -207,14 +202,8 @@ export class Keyring implements KeyringInstance { * @name createFromUri * @summary Creates a Keypair from an suri * @description This creates a pair from the suri, but does not add it to the keyring - * - * @param _suri - * @param meta - * @param type The supported types of pairs. Either 'ed25519' | 'sr25519' | 'ecdsa' | 'ethereum'. - * @param wordlist - Optional custom wordlist for mnemonic. - * @param rounds - Optional: Number of PBKDF2 iterations to run (default: 210000 (when onlyJS = true) or 2048 (when onlyJS = false). */ - public createFromUri (_suri: string, meta: KeyringPair$Meta = {}, type: KeypairType = this.type, wordlist?: string[], rounds?: number): KeyringPair { + public createFromUri (_suri: string, meta: KeyringPair$Meta = {}, type: KeypairType = this.type, wordlist?: string[]): KeyringPair { // here we only aut-add the dev phrase if we have a hard-derived path const suri = _suri.startsWith('//') ? `${DEV_PHRASE}${_suri}` @@ -230,8 +219,8 @@ export class Keyring implements KeyringInstance { if ([12, 15, 18, 21, 24].includes(parts.length)) { seed = type === 'ethereum' - ? mnemonicToLegacySeed(phrase, '', false, 64, rounds) - : mnemonicToMiniSecret(phrase, password, wordlist, false, rounds); + ? mnemonicToLegacySeed(phrase, '', false, 64) + : mnemonicToMiniSecret(phrase, password, wordlist); } else { if (phrase.length > 32) { throw new Error('specified phrase is not a valid mnemonic and is invalid as a raw seed at > 32 bytes'); diff --git a/packages/keyring/src/suri.spec.ts b/packages/keyring/src/suri.spec.ts index 72d81cd12d..519395a13e 100644 --- a/packages/keyring/src/suri.spec.ts +++ b/packages/keyring/src/suri.spec.ts @@ -98,7 +98,7 @@ describe('keyring.addFromUri', (): void => { describe(`${type}`, (): void => { tests.forEach(({ pk, ss, uri }): void => { it(`creates ${uri}`, (): void => { - const pair = keyring.addFromUri(uri, {}, type as KeypairType, undefined, 2048); + const pair = keyring.addFromUri(uri, {}, type as KeypairType); expect(u8aToHex(pair.publicKey)).toEqual(pk); expect(pair.address).toEqual(ss); diff --git a/packages/util-crypto/src/hd/ethereum/index.spec.ts b/packages/util-crypto/src/hd/ethereum/index.spec.ts index 50bd19cf62..733e6a2740 100644 --- a/packages/util-crypto/src/hd/ethereum/index.spec.ts +++ b/packages/util-crypto/src/hd/ethereum/index.spec.ts @@ -39,14 +39,14 @@ describe('hdEthereum', (): void => { ]); it('derives the right key pair from a mnemonic', (): void => { - const key = hdEthereum(mnemonicToLegacySeed(PHRASE, '', false, 64, 2048)); + const key = hdEthereum(mnemonicToLegacySeed(PHRASE, '', false, 64)); expect(key.publicKey).toEqual(PUBLIC); expect(key.secretKey).toEqual(SECRET); }); it('derives the right key pair from a mnemonic and a derivation path', (): void => { - const key = hdEthereum(mnemonicToLegacySeed(PHRASE, '', false, 64, 2048), derivationPath); + const key = hdEthereum(mnemonicToLegacySeed(PHRASE, '', false, 64), derivationPath); expect(key.publicKey).toEqual(PUBLICDERIVED); expect(key.secretKey).toEqual(SECRETDERIVED); diff --git a/packages/util-crypto/src/hd/ledger/index.spec.ts b/packages/util-crypto/src/hd/ledger/index.spec.ts index 836964ec73..7adcb14ac9 100644 --- a/packages/util-crypto/src/hd/ledger/index.spec.ts +++ b/packages/util-crypto/src/hd/ledger/index.spec.ts @@ -54,7 +54,7 @@ describe('ledgerDerive', (): void => { tests.forEach(({ ed25519, index: [account, address], mnemonic }, index): void => { it(`derives a known ed25519 seed for ${network} (${index})`, (): void => { expect(u8aToHex( - hdLedger(mnemonic, `m/44'/${slip44}'/${account}'/0'/${address}'`, 2048) + hdLedger(mnemonic, `m/44'/${slip44}'/${account}'/0'/${address}'`) .secretKey .slice(0, 32) )).toEqual(ed25519); diff --git a/packages/util-crypto/src/hd/ledger/index.ts b/packages/util-crypto/src/hd/ledger/index.ts index f954e9f52a..818b2aafdf 100644 --- a/packages/util-crypto/src/hd/ledger/index.ts +++ b/packages/util-crypto/src/hd/ledger/index.ts @@ -9,7 +9,7 @@ import { HARDENED, hdValidatePath } from '../validatePath.js'; import { ledgerDerivePrivate } from './derivePrivate.js'; import { ledgerMaster } from './master.js'; -export function hdLedger (_mnemonic: string, path: string, rounds?: number): Keypair { +export function hdLedger (_mnemonic: string, path: string): Keypair { const words = _mnemonic .split(' ') .map((s) => s.trim()) @@ -30,7 +30,7 @@ export function hdLedger (_mnemonic: string, path: string, rounds?: number): Key } const parts = path.split('/').slice(1); - let seed = ledgerMaster(mnemonic, password, rounds); + let seed = ledgerMaster(mnemonic, password); for (const p of parts) { const n = parseInt(p.replace(/'$/, ''), 10); diff --git a/packages/util-crypto/src/hd/ledger/master.spec.ts b/packages/util-crypto/src/hd/ledger/master.spec.ts index ec0d3acc23..d96d5a7d0f 100644 --- a/packages/util-crypto/src/hd/ledger/master.spec.ts +++ b/packages/util-crypto/src/hd/ledger/master.spec.ts @@ -13,7 +13,7 @@ const XPRV = '0x402b03cd9c8bed9ba9f9bd6cd9c315ce9fcc59c7c25d37c85a36096617e69d41 describe('ledgerDerive', (): void => { it('derives a known master xprv', (): void => { expect(u8aToHex( - ledgerMaster(MNEMONIC, undefined, 2048) + ledgerMaster(MNEMONIC) )).toEqual(XPRV); }); }); diff --git a/packages/util-crypto/src/hd/ledger/master.ts b/packages/util-crypto/src/hd/ledger/master.ts index cf43a3d05e..3b4b1a9dca 100644 --- a/packages/util-crypto/src/hd/ledger/master.ts +++ b/packages/util-crypto/src/hd/ledger/master.ts @@ -8,17 +8,9 @@ import { mnemonicToSeedSync } from '../../mnemonic/bip39.js'; const ED25519_CRYPTO = 'ed25519 seed'; -/** - * Gets an xprv from a mnemonic - * - * @param mnemonic - The BIP-39 mnemonic phrase to derive the secret from. - * @param password - Optional: password to secure the seed (default: empty string). - * @param wordlist - Optional custom wordlist for mnemonic. - * @param onlyJs - Optional: If `true`, forces use of the JavaScript implementation instead of WASM. - * @param rounds - Optional: Number of PBKDF2 iterations to run (default: 210000). -*/ -export function ledgerMaster (mnemonic: string, password?: string, rounds?: number): Uint8Array { - const seed = mnemonicToSeedSync(mnemonic, password, rounds); +// gets an xprv from a mnemonic +export function ledgerMaster (mnemonic: string, password?: string): Uint8Array { + const seed = mnemonicToSeedSync(mnemonic, password); const chainCode = hmacShaAsU8a(ED25519_CRYPTO, new Uint8Array([1, ...seed]), 256); let priv; diff --git a/packages/util-crypto/src/mnemonic/bip39.ts b/packages/util-crypto/src/mnemonic/bip39.ts index fcb5b213e4..c04f93b912 100644 --- a/packages/util-crypto/src/mnemonic/bip39.ts +++ b/packages/util-crypto/src/mnemonic/bip39.ts @@ -47,16 +47,10 @@ function deriveChecksumBits (entropyBuffer: Uint8Array): string { ).slice(0, (entropyBuffer.length * 8) / 32); } -/* - * @param mnemonic - The BIP-39 mnemonic phrase to derive the secret from. - * @param password - Optional: password to secure the seed (default: empty string). - * @param rounds - Optional: Number of PBKDF2 iterations to run (default: 210000). -*/ -export function mnemonicToSeedSync (mnemonic: string, password?: string, rounds?: number): Uint8Array { +export function mnemonicToSeedSync (mnemonic: string, password?: string): Uint8Array { return pbkdf2Encode( stringToU8a(normalize(mnemonic)), - stringToU8a(`mnemonic${normalize(password)}`), - rounds + stringToU8a(`mnemonic${normalize(password)}`) ).password; } diff --git a/packages/util-crypto/src/mnemonic/toLegacySeed.spec.ts b/packages/util-crypto/src/mnemonic/toLegacySeed.spec.ts index 78cdb42975..79b66225ac 100644 --- a/packages/util-crypto/src/mnemonic/toLegacySeed.spec.ts +++ b/packages/util-crypto/src/mnemonic/toLegacySeed.spec.ts @@ -21,8 +21,8 @@ describe('mnemonicToLegacySeed', (): void => { it(`generates Wasm & Js equivalents for password=${password || 'undefined'}`, (): void => { expect( u8aEq( - mnemonicToLegacySeed(MNEMONIC, password, true, 32, 2048), - mnemonicToLegacySeed(MNEMONIC, password, false, 32, 2048) + mnemonicToLegacySeed(MNEMONIC, password, true), + mnemonicToLegacySeed(MNEMONIC, password, false) ) ).toEqual(true); }); @@ -32,19 +32,19 @@ describe('mnemonicToLegacySeed', (): void => { describe(`onlyJs=${(onlyJs && 'true') || 'false'}`, (): void => { it('generates a valid 64bytes seed', (): void => { expect( - u8aToHex(mnemonicToLegacySeed(MNEMONIC, undefined, onlyJs, 64, 2048)) + u8aToHex(mnemonicToLegacySeed(MNEMONIC, undefined, onlyJs, 64)) ).toEqual(SEED_64); }); it('generates a valid 32bytes seed', (): void => { expect( - u8aToHex(mnemonicToLegacySeed(MNEMONIC, undefined, onlyJs, 32, 2048)) + u8aToHex(mnemonicToLegacySeed(MNEMONIC, undefined, onlyJs)) ).toEqual(SEED_32); }); it('fails with non-mnemonics', (): void => { expect( - () => mnemonicToLegacySeed('foo bar baz', undefined, onlyJs, 32, 2048) + () => mnemonicToLegacySeed('foo bar baz', undefined, onlyJs) ).toThrow(/mnemonic specified/); }); }); diff --git a/packages/util-crypto/src/mnemonic/toLegacySeed.ts b/packages/util-crypto/src/mnemonic/toLegacySeed.ts index 188898cc8e..3249642092 100644 --- a/packages/util-crypto/src/mnemonic/toLegacySeed.ts +++ b/packages/util-crypto/src/mnemonic/toLegacySeed.ts @@ -23,14 +23,8 @@ import { mnemonicValidate } from './validate.js'; * console.log(`Seed generated from mnemonic: ${mnemonicToLegacySeed(mnemonic)}`); => u8a * } * ``` - * - * @param mnemonic - The BIP-39 mnemonic phrase to derive the secret from. - * @param password - Optional: password to secure the seed (default: empty string). - * @param onlyJs - Optional: If `true`, forces use of the JavaScript implementation instead of WASM. - * @param byteLength - Optional: Either 32 or 64. Default is 32 - * @param rounds - Optional: Number of PBKDF2 iterations to run (default: 210000). -*/ -export function mnemonicToLegacySeed (mnemonic: string, password = '', onlyJs?: boolean, byteLength: 32 | 64 = 32, rounds?: number): Uint8Array { + */ +export function mnemonicToLegacySeed (mnemonic: string, password = '', onlyJs?: boolean, byteLength: 32 | 64 = 32): Uint8Array { if (!mnemonicValidate(mnemonic)) { throw new Error('Invalid bip39 mnemonic specified'); } else if (![32, 64].includes(byteLength)) { @@ -40,6 +34,6 @@ export function mnemonicToLegacySeed (mnemonic: string, password = '', onlyJs?: return byteLength === 32 ? !hasBigInt || (!onlyJs && isReady()) ? bip39ToSeed(mnemonic, password) - : mnemonicToSeedSync(mnemonic, password, rounds).subarray(0, 32) - : mnemonicToSeedSync(mnemonic, password, rounds); + : mnemonicToSeedSync(mnemonic, password).subarray(0, 32) + : mnemonicToSeedSync(mnemonic, password); } diff --git a/packages/util-crypto/src/mnemonic/toMiniSecret.spec.ts b/packages/util-crypto/src/mnemonic/toMiniSecret.spec.ts index 37580f26be..e1e5f554dc 100644 --- a/packages/util-crypto/src/mnemonic/toMiniSecret.spec.ts +++ b/packages/util-crypto/src/mnemonic/toMiniSecret.spec.ts @@ -20,8 +20,8 @@ describe('mnemonicToMiniSecret', (): void => { it(`generates Wasm & Js equivalents for password=${password || 'undefined'}`, (): void => { expect( u8aEq( - mnemonicToMiniSecret(MNEMONIC, password, undefined, true, 2048), - mnemonicToMiniSecret(MNEMONIC, password, undefined, false, 2048) + mnemonicToMiniSecret(MNEMONIC, password, undefined, true), + mnemonicToMiniSecret(MNEMONIC, password, undefined, false) ) ).toEqual(true); }); @@ -31,10 +31,10 @@ describe('mnemonicToMiniSecret', (): void => { const mnemonic = '엉덩이 능동적 숫자 팩시밀리 비난 서적 파출소 도움 독창적 인생 상류 먼지 답변 음반 수박 사업 노란색 공사 우체국 특급 도대체 금지 굉장히 고무신'; expect( - () => mnemonicToMiniSecret(mnemonic, 'testing', undefined, false, 2048) + () => mnemonicToMiniSecret(mnemonic, 'testing') ).toThrow(); expect( - u8aToHex(mnemonicToMiniSecret(mnemonic, 'testing', koreanWords, false, 2048)) + u8aToHex(mnemonicToMiniSecret(mnemonic, 'testing', koreanWords)) ).toEqual('0xefa278a62535581767a2f49cb542ed91b65fb911e1b05e7a09c702b257f10c13'); }); @@ -42,20 +42,20 @@ describe('mnemonicToMiniSecret', (): void => { describe(`onlyJs=${(onlyJs && 'true') || 'false'}`, (): void => { it('generates a valid seed', (): void => { expect( - u8aToHex(mnemonicToMiniSecret(MNEMONIC, undefined, undefined, onlyJs, 2048)) + u8aToHex(mnemonicToMiniSecret(MNEMONIC, undefined, undefined, onlyJs)) ).toEqual(SEED); }); it('fails with non-mnemonics', (): void => { expect( - () => mnemonicToMiniSecret('foo bar baz', undefined, undefined, onlyJs, 2048) + () => mnemonicToMiniSecret('foo bar baz', undefined, undefined, onlyJs) ).toThrow(/mnemonic specified/); }); tests.forEach(([mnemonic, , seed], index): void => { it(`Created correct seed for ${index}`, (): void => { expect( - u8aToHex(mnemonicToMiniSecret(mnemonic, 'Substrate', undefined, onlyJs, 2048)) + u8aToHex(mnemonicToMiniSecret(mnemonic, 'Substrate', undefined, onlyJs)) ).toEqual( // mini returned here, only check first 32-bytes (64 hex + 2 prefix) seed.substring(0, 66) diff --git a/packages/util-crypto/src/mnemonic/toMiniSecret.ts b/packages/util-crypto/src/mnemonic/toMiniSecret.ts index caed179f7b..7e70484a0c 100644 --- a/packages/util-crypto/src/mnemonic/toMiniSecret.ts +++ b/packages/util-crypto/src/mnemonic/toMiniSecret.ts @@ -8,14 +8,7 @@ import { pbkdf2Encode } from '../pbkdf2/index.js'; import { mnemonicToEntropy } from './toEntropy.js'; import { mnemonicValidate } from './validate.js'; -/** - * @param mnemonic - The BIP-39 mnemonic phrase to derive the secret from. - * @param password - Optional: password to secure the seed (default: empty string). - * @param wordlist - Optional custom wordlist for mnemonic. - * @param onlyJs - Optional: If `true`, forces use of the JavaScript implementation instead of WASM. - * @param rounds - Optional: Number of PBKDF2 iterations to run (default: 210000 (when onlyJS = true) or 2048 (when onlyJS = false). -*/ -export function mnemonicToMiniSecret (mnemonic: string, password = '', wordlist?: string[], onlyJs?: boolean, rounds?: number): Uint8Array { +export function mnemonicToMiniSecret (mnemonic: string, password = '', wordlist?: string[], onlyJs?: boolean): Uint8Array { if (!mnemonicValidate(mnemonic, wordlist, onlyJs)) { throw new Error('Invalid bip39 mnemonic specified'); } else if (!wordlist && !onlyJs && isReady()) { @@ -26,5 +19,5 @@ export function mnemonicToMiniSecret (mnemonic: string, password = '', wordlist? const salt = stringToU8a(`mnemonic${password}`); // return the first 32 bytes as the seed - return pbkdf2Encode(entropy, salt, rounds).password.slice(0, 32); + return pbkdf2Encode(entropy, salt).password.slice(0, 32); } diff --git a/packages/util-crypto/src/pbkdf2/encode.spec.ts b/packages/util-crypto/src/pbkdf2/encode.spec.ts index 071b934dc5..69f112e1ae 100644 --- a/packages/util-crypto/src/pbkdf2/encode.spec.ts +++ b/packages/util-crypto/src/pbkdf2/encode.spec.ts @@ -49,6 +49,6 @@ describe('pbkdf2Encode', (): void => { } perfWasm('pbkdf2Encode', 8, (input, onlyJs) => - pbkdf2Encode(input, input, 2048, onlyJs) + pbkdf2Encode(input, input, undefined, onlyJs) ); }); diff --git a/packages/util-crypto/src/pbkdf2/encode.ts b/packages/util-crypto/src/pbkdf2/encode.ts index b5c86125bb..2c2a6dea16 100644 --- a/packages/util-crypto/src/pbkdf2/encode.ts +++ b/packages/util-crypto/src/pbkdf2/encode.ts @@ -15,14 +15,7 @@ interface Result { salt: Uint8Array; } -export function pbkdf2Encode (passphrase?: string | Uint8Array, salt: Uint8Array = randomAsU8a(), rounds = 210000, onlyJs?: boolean): Result { - // When using the JS implementation (pbkdf2Js), large iteration counts can - // cause excessive computation time or memory usage. In that case, we cap - // the number of rounds to 2048 to ensure reliable performance. - if (onlyJs && rounds > 2048) { - rounds = 2048; - } - +export function pbkdf2Encode (passphrase?: string | Uint8Array, salt: Uint8Array = randomAsU8a(), rounds = 2048, onlyJs?: boolean): Result { const u8aPass = u8aToU8a(passphrase); const u8aSalt = u8aToU8a(salt);