def decode(secret, _bip39pw=''): # expecting 72-bytes of secret payload; decode contents into objects # returns: # type, secrets bytes, HDNode(root) # marker = secret[0] hd = ngu.hdnode.HDNode() if marker == 0x01: # xprv => BIP-32 private key values ch, pk = secret[1:33], secret[33:65] assert not _bip39pw hd.from_chaincode_privkey(ch, pk) return 'xprv', ch + pk, hd if marker & 0x80: # seed phrase ll = ((marker & 0x3) + 2) * 8 # note: # - byte length > number of words # - not storing checksum assert ll in [16, 24, 32] # make master secret, using the memonic words, and passphrase (or empty string) seed_bits = secret[1:1 + ll] ms = bip39.master_secret(bip39.b2a_words(seed_bits), _bip39pw) hd.from_master(ms) return 'words', seed_bits, hd else: # variable-length master secret for BIP-32 vlen = secret[0] assert 16 <= vlen <= 64 assert not _bip39pw ms = secret[1:1 + vlen] hd = hd.from_master(ms) return 'master', ms, hd
def test_vectors(): for raw, words, ms, _ in b39_vectors.english[0:10]: assert bip39.a2b_words(words) == a2b_hex(raw) got = bip39.master_secret(words.encode('utf'), a2b_hex('5452455a4f52')) assert got == a2b_hex(ms)