Additional hdLedger tests (#863)

This commit is contained in:
Jaco Greeff
2021-02-01 14:39:14 +01:00
committed by GitHub
parent 54e6b61972
commit c2f453481c
2 changed files with 62 additions and 35 deletions
@@ -1,34 +1,29 @@
// Copyright 2017-2021 @polkadot/util-crypto authors & contributors
// SPDX-License-Identifier: Apache-2.0
import BN from 'bn.js';
import { bnToU8a, u8aConcat } from '@polkadot/util';
import { bnToU8a, u8aConcat, u8aToBn } from '@polkadot/util';
import { hmacSha512 } from '../../hmac';
// performs hard-only derivation on the xprv
export function ledgerDerivePrivate (xprv: Uint8Array, index: number): Uint8Array {
const kl = xprv.slice(0, 32);
const kr = xprv.slice(32, 64);
const cc = xprv.slice(64, 96);
const data = new Uint8Array(1 + 64 + 4);
data.set(bnToU8a(index, { bitLength: 32, isLe: true }), 1 + 64);
data.set(kl, 1);
data.set(kr, 1 + 32);
data[0] = 0x00;
const kl = xprv.subarray(0, 32);
const kr = xprv.subarray(32, 64);
const cc = xprv.subarray(64, 96);
const data = u8aConcat([0], kl, kr, bnToU8a(index, { bitLength: 32, isLe: true }));
const z = hmacSha512(cc, data);
data[0] = 0x01;
const chainCode = hmacSha512(cc, data).slice(32, 64);
const zl = z.slice(0, 32);
const zr = z.slice(32, 64);
const left = bnToU8a(new BN(kl, 16, 'le').add(new BN(zl.slice(0, 28), 16, 'le').mul(new BN(8))), { bitLength: 512, isLe: true }).slice(0, 32);
const right = bnToU8a(new BN(kr, 16, 'le').add(new BN(zr, 16, 'le')), { bitLength: 512, isLe: true }).slice(0, 32);
return u8aConcat(left, right, chainCode);
return u8aConcat(
bnToU8a(
u8aToBn(kl, { isLe: true }).iadd(u8aToBn(z.subarray(0, 28), { isLe: true }).muln(8)),
{ bitLength: 512, isLe: true }
).subarray(0, 32),
bnToU8a(
u8aToBn(kr, { isLe: true }).iadd(u8aToBn(z.subarray(32, 64), { isLe: true })),
{ bitLength: 512, isLe: true }
).subarray(0, 32),
hmacSha512(cc, data).subarray(32, 64)
);
}
@@ -5,20 +5,52 @@ import { u8aToHex } from '@polkadot/util';
import { hdLedger } from '..';
describe('ledgerDerive', (): void => {
it('derives a known private key for Kusama', (): void => {
expect(u8aToHex(
hdLedger('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about', `m/44'/${0x01b2}'/0'/0'/0'`)
.secretKey
.slice(0, 32)
)).toEqual('0x98cb4e14e0e08ea876f88d728545ea7572dc07dbbe69f1731c418fb827e69d41');
});
const MNE_0 = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
const MNE_1 = 'open jelly jeans corn ketchup supreme brief element armed lens vault weather original scissors rug priority vicious lesson raven spot gossip powder person volcano';
it('derives a known private key for Polkadot', (): void => {
expect(u8aToHex(
hdLedger('abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about', `m/44'/${0x80000162}/0'/0'/0'`)
.secretKey
.slice(0, 32)
)).toEqual('0xe8c68348586d53e4e8d1a864b0e4e17c75e4eb06e0c63c1432bef2ba29e69d41');
const TESTS = {
Kusama: {
slip44: 0x01b2,
tests: [
{
ed25519: '0x98cb4e14e0e08ea876f88d728545ea7572dc07dbbe69f1731c418fb827e69d41',
index: [0, 0],
mnemonic: MNE_0
},
{
ed25519: '0x70e9010e84c81095aaa5f63b1c5a6a66a1dcbec017a23c2f3b7a1b08fe5ea65a',
index: [0, 0],
mnemonic: MNE_1
},
{
ed25519: '0xf06730efb1e6ea59ac752a7c3620fade3909062fb88597856cc3af72045fa65a',
index: [5, 7],
mnemonic: MNE_1
}
]
},
Polkadot: {
slip44: 0x80000162,
tests: [
{
ed25519: '0xe8c68348586d53e4e8d1a864b0e4e17c75e4eb06e0c63c1432bef2ba29e69d41',
index: [0, 0],
mnemonic: MNE_0
}
]
}
};
describe('ledgerDerive', (): void => {
Object.entries(TESTS).forEach(([network, { slip44, tests }]): 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}'`)
.secretKey
.slice(0, 32)
)).toEqual(ed25519);
});
});
});
});