Open
Description
The principal_id generated locally through the seed is inconsistent with the principal_id displayed on the nns dapp:
Take the following two pieces of code as an example:
seed:1947400 story goddess birth execute canoe sense poverty orchard feel mule indoor credit bulb arrest primary giggle turtle order tell glimpse grid act motion february
nns generated: jwfy3-6d6bo-ri5le-apblk-7tmrd-h7sj5-srhi4-4wntx-4daz6-missz-yqe
local generated: nrw4v-2qe5h-dor7z-mm7x4-hfa5f-tfls6-avaja-aysww-c6bwg-g25mq-jqe
local code
import { Ed25519KeyIdentity } from '@dfinity/identity';
import { mnemonicToSeedSync } from "bip39";
import {
pub_key_to_address,
} from '@dfinity/rosetta-client';
let crypto;
const HARDENED = 0x80000000;
function toBigEndianArray(n) {
const byteArray = new Uint8Array([0, 0, 0, 0]);
for (let i = byteArray.length - 1; i >= 0; i--) {
const byte = n & 0xff;
byteArray[i] = byte;
n = (n - byte) / 256;
}
return byteArray;
}
async function derive(
parentKey,
parentChaincode,
i,
) {
// From the spec: Data = 0x00 || ser256(kpar) || ser32(i)
const data = new Uint8Array([0, ...parentKey, ...toBigEndianArray(i)]);
const key = await crypto.subtle.importKey(
'raw',
parentChaincode,
{
name: 'HMAC',
hash: { name: 'SHA-512' },
},
false,
['sign'],
);
const h = await crypto.subtle.sign('HMAC', key, data.buffer);
const slipSeed = new Uint8Array(h.slice(0, 32));
const chainCode = new Uint8Array(h.slice(32));
return [slipSeed, chainCode];
}
async function generateMasterKey(
seed,
) {
const data = new TextEncoder().encode('ed25519 seed');
const key = await crypto.subtle.importKey(
'raw',
data,
{
name: 'HMAC',
hash: { name: 'SHA-512' },
},
false,
['sign'],
);
const h = await crypto.subtle.sign('HMAC', key, seed);
const slipSeed = new Uint8Array(h.slice(0, 32));
const chainCode = new Uint8Array(h.slice(32));
return [slipSeed, chainCode];
}
export async function fromSeedWithSlip0010(
masterSeed,
derivationPath,
) {
let [slipSeed, chainCode] = await generateMasterKey(masterSeed);
for (let i = 0; i < derivationPath.length; i++) {
[slipSeed, chainCode] = await derive(
slipSeed,
chainCode,
derivationPath[i] | HARDENED,
);
}
return Ed25519KeyIdentity.generate(slipSeed);
}
async function main() {
try {
crypto = await import('node:crypto');
} catch (err) {
console.log('crypto support is disabled!');
}
crypto.subtle
const mem = "story goddess birth execute canoe sense poverty orchard feel mule indoor credit bulb arrest primary giggle turtle order tell glimpse grid act motion february"
const seed = mnemonicToSeedSync(mem);
const id = await fromSeedWithSlip0010(seed, [44, 223, 0, 0, 0]);
console.log(id.getPublicKey().toDer())
// console.log(pub_key_to_address(id.getPublicKey()))
}
main()
nns-dapp code
import { Ed25519KeyIdentity } from '@dfinity/identity';
import { mnemonicToSeedSync } from "bip39";
let crypto;
const HARDENED = 0x80000000;
function toBigEndianArray(n) {
const byteArray = new Uint8Array([0, 0, 0, 0]);
for (let i = byteArray.length - 1; i >= 0; i--) {
const byte = n & 0xff;
byteArray[i] = byte;
n = (n - byte) / 256;
}
return byteArray;
}
async function derive(
parentKey,
parentChaincode,
i,
) {
// From the spec: Data = 0x00 || ser256(kpar) || ser32(i)
const data = new Uint8Array([0, ...parentKey, ...toBigEndianArray(i)]);
const key = await crypto.subtle.importKey(
'raw',
parentChaincode,
{
name: 'HMAC',
hash: { name: 'SHA-512' },
},
false,
['sign'],
);
const h = await crypto.subtle.sign('HMAC', key, data.buffer);
const slipSeed = new Uint8Array(h.slice(0, 32));
const chainCode = new Uint8Array(h.slice(32));
return [slipSeed, chainCode];
}
async function generateMasterKey(
seed,
) {
const data = new TextEncoder().encode('ed25519 seed');
const key = await crypto.subtle.importKey(
'raw',
data,
{
name: 'HMAC',
hash: { name: 'SHA-512' },
},
false,
['sign'],
);
const h = await crypto.subtle.sign('HMAC', key, seed);
const slipSeed = new Uint8Array(h.slice(0, 32));
const chainCode = new Uint8Array(h.slice(32));
return [slipSeed, chainCode];
}
export async function fromSeedWithSlip0010(
masterSeed,
derivationPath,
) {
let [slipSeed, chainCode] = await generateMasterKey(masterSeed);
for (let i = 0; i < derivationPath.length; i++) {
[slipSeed, chainCode] = await derive(
slipSeed,
chainCode,
derivationPath[i] | HARDENED,
);
}
return Ed25519KeyIdentity.generate(slipSeed);
}
async function main() {
try {
crypto = await import('node:crypto');
} catch (err) {
console.log('crypto support is disabled!');
}
crypto.subtle
const mem = "story goddess birth execute canoe sense poverty orchard feel mule indoor credit bulb arrest primary giggle turtle order tell glimpse grid act motion february"
const seed = mnemonicToSeedSync(mem);
const id = await fromSeedWithSlip0010(seed, [44, 223, 0, 0, 0]);
console.log(id.getPrincipal().toString())
}
main()
Metadata
Metadata
Assignees
Labels
No labels