익명 00:29

Invalid checksum when generating BIP-39 Mnemonic

Invalid checksum when generating BIP-39 Mnemonic

I am trying to generate a mnemonic seed in Javascript, and while everything seems to be working, I am not getting a mnemonic with a correct checksum. Here is my implementation:

export const generateMnemonic = async () => {
    const ent = window.crypto.getRandomValues(new Uint8Array(16));
    const entBits = toBinString(ent);
    const entHash = Array.from(new Uint8Array(
        await window.crypto.subtle.digest("SHA-256", ent)
    ));
    const entHashBits = toBinString(entHash)
    const checksum = entHashBits.slice(0, 4);
    const entCS = entBits + checksum;
    const chunks = Array.from(hendecadsFromBits(entCS));
    const words = [];
    for (let i = 0; i < chunks.length; i++) {
        words.push(wordlist[chunks[i]]);
    }
    return words;
};

const toBinString = (bytes) => bytes.reduce((str, byte) => str + byte.toString(2).padStart(8, '0'), '')

function* hendecadsFromBits(bits) {
    let i = 0;
    let val = 0;
    for (const bit of bits) {
        if (i == 11) {
            yield val;
            i = val = 0;
        }
        val |= bit << i++;
    }
    if (i > 0) yield val;
}

Is it because I am padding the bytes with zeros?

I would really appreciate your help!



Top Answer/Comment:

There is a few problem in your code, in the hendecadsFromBits function, you need to use the numeric value of bit and in the generateMnemonic function, when you call hendecadsFromBits, you need to pass the result to Array.from()

Here is how you could fix your code:

export const generateMnemonic = async () => {
    const ent = window.crypto.getRandomValues(new Uint8Array(16));
    const entBits = toBinString(ent);
    const entHash = Array.from(new Uint8Array(
        await window.crypto.subtle.digest("SHA-256", ent)
    ));
    const entHashBits = toBinString(entHash)
    const checksum = entHashBits.slice(0, 4);
    const entCS = entBits + checksum;
    const chunks = Array.from(hendecadsFromBits(entCS));
    const words = [];

    for (let i = 0; i < chunks.length; i++) {
        words.push(wordlist[chunks[i]]);
    }
    return words.join(' ');
};

const toBinString = (bytes) => bytes.reduce((str, byte) => str + byte.toString(2).padStart(8, '0'), '')

function* hendecadsFromBits(bits) {
    let i = 0;
    let val = 0;
    for (const bit of bits) {
        if (i == 11) {
            yield val;
            i = val = 0;
        }
        val |= parseInt(bit, 10) << i++;
    }
    if (i > 0) yield val;
}
상단 광고의 [X] 버튼을 누르면 내용이 보입니다