This reverts commit e5e6bdd814.
This commit is contained in:
committed by
GitHub
parent
047840319e
commit
2212f31f9a
@@ -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
|
||||
|
||||
@@ -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 `<secret>/<soft-key>//<hard-key>///<password>` (the `///password` may be omitted, and `/<soft-key>` and `//<hard-key>` 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');
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,6 @@ describe('pbkdf2Encode', (): void => {
|
||||
}
|
||||
|
||||
perfWasm('pbkdf2Encode', 8, (input, onlyJs) =>
|
||||
pbkdf2Encode(input, input, 2048, onlyJs)
|
||||
pbkdf2Encode(input, input, undefined, onlyJs)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user