Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to support looking up mnemonic by just the first 4 letters of each word #16704

Merged
merged 14 commits into from
Nov 1, 2023
Merged
26 changes: 25 additions & 1 deletion chia/util/keychain.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,31 @@ def bytes_to_mnemonic(mnemonic_bytes: bytes) -> str:
return " ".join(mnemonics)


def bytes_from_mnemonic(mnemonic_str: str) -> bytes:
def mnemonic_from_short_words(mnemonic_str: str) -> str:
"""
Since the first 4 letters of each word is unique (or the full word, if less than 4 characters), and its common
practice to only store the first 4 letters of each word in many offline storage solutions, also support looking
up words by the first 4 characters
"""
mnemonic: List[str] = mnemonic_str.split(" ")
if len(mnemonic) not in [12, 15, 18, 21, 24]:
raise ValueError("Invalid mnemonic length")

four_char_dict = {word[:4]: word for word in bip39_word_list().splitlines()}
full_words: List[str] = []
for word in mnemonic:
full_word = four_char_dict.get(word[:4])
if full_word is None:
raise ValueError(f"{word!r} is not in the mnemonic dictionary; may be misspelled")
full_words.append(full_word)

return " ".join(full_words)


def bytes_from_mnemonic(mnemonic_str: str) -> bytes:
full_mnemonic_str = mnemonic_from_short_words(mnemonic_str)
mnemonic: List[str] = full_mnemonic_str.split(" ")

word_list = {word: i for i, word in enumerate(bip39_word_list().splitlines())}
bit_array = BitArray()
for i in range(0, len(mnemonic)):
Expand Down Expand Up @@ -123,6 +143,10 @@ def mnemonic_to_seed(mnemonic: str) -> bytes:
"""
Uses BIP39 standard to derive a seed from entropy bytes.
"""
# If there are only ASCII characters (as typically expected in a seed phrase), we can check if its just shortened
# 4 letter versions of each word
if not any(ord(c) >= 128 for c in mnemonic):
mnemonic = mnemonic_from_short_words(mnemonic)
salt_str: str = "mnemonic"
salt = unicodedata.normalize("NFKD", salt_str).encode("utf-8")
mnemonic_normalized = unicodedata.normalize("NFKD", mnemonic).encode("utf-8")
Expand Down
20 changes: 20 additions & 0 deletions tests/core/util/test_keychain.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from __future__ import annotations

import json
import pathlib
import random
from dataclasses import replace
from typing import Callable, List, Optional, Tuple

import pytest
from blspy import AugSchemeMPL, G1Element, PrivateKey

import tests
from chia.simulator.keyring import TempKeyring
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.util.errors import (
Expand All @@ -26,6 +28,7 @@
bytes_from_mnemonic,
bytes_to_mnemonic,
generate_mnemonic,
mnemonic_from_short_words,
mnemonic_to_seed,
)

Expand Down Expand Up @@ -165,6 +168,23 @@ def test_bip39_test_vectors(self):
assert bytes_to_mnemonic(entropy_bytes) == mnemonic
assert mnemonic_to_seed(mnemonic) == seed

def test_bip39_test_vectors_short(self):
"""
Tests that the first 4 letters of each mnemonic phrase matches as if it were the full phrase
"""
test_vectors_path = pathlib.Path(tests.__file__).parent.joinpath("util", "bip39_test_vectors.json")
with open(test_vectors_path) as f:
all_vectors = json.load(f)

for idx, [entropy_hex, full_mnemonic, seed, short_mnemonic] in enumerate(all_vectors["english"]):
entropy_bytes = bytes.fromhex(entropy_hex)
seed = bytes.fromhex(seed)

assert mnemonic_from_short_words(short_mnemonic) == full_mnemonic
assert bytes_from_mnemonic(short_mnemonic) == entropy_bytes
assert bytes_to_mnemonic(entropy_bytes) == full_mnemonic
assert mnemonic_to_seed(short_mnemonic) == seed

def test_utf8_nfkd(self):
# Test code from trezor:
# Copyright (c) 2013 Pavol Rusnak
Expand Down
72 changes: 48 additions & 24 deletions tests/util/bip39_test_vectors.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,122 +3,146 @@
[
"00000000000000000000000000000000",
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
"5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4"
"5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4",
"aban aban aban aban aban aban aban aban aban aban aban abou"
],
[
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
"legal winner thank year wave sausage worth useful legal winner thank yellow",
"878386efb78845b3355bd15ea4d39ef97d179cb712b77d5c12b6be415fffeffe5f377ba02bf3f8544ab800b955e51fbff09828f682052a20faa6addbbddfb096"
"878386efb78845b3355bd15ea4d39ef97d179cb712b77d5c12b6be415fffeffe5f377ba02bf3f8544ab800b955e51fbff09828f682052a20faa6addbbddfb096",
"lega winn than year wave saus wort usef lega winn than yell"
],
[
"80808080808080808080808080808080",
"letter advice cage absurd amount doctor acoustic avoid letter advice cage above",
"77d6be9708c8218738934f84bbbb78a2e048ca007746cb764f0673e4b1812d176bbb173e1a291f31cf633f1d0bad7d3cf071c30e98cd0688b5bcce65ecaceb36"
"77d6be9708c8218738934f84bbbb78a2e048ca007746cb764f0673e4b1812d176bbb173e1a291f31cf633f1d0bad7d3cf071c30e98cd0688b5bcce65ecaceb36",
"lett advi cage absu amou doct acou avoi lett advi cage abov"
],
[
"ffffffffffffffffffffffffffffffff",
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
"b6a6d8921942dd9806607ebc2750416b289adea669198769f2e15ed926c3aa92bf88ece232317b4ea463e84b0fcd3b53577812ee449ccc448eb45e6f544e25b6"
"b6a6d8921942dd9806607ebc2750416b289adea669198769f2e15ed926c3aa92bf88ece232317b4ea463e84b0fcd3b53577812ee449ccc448eb45e6f544e25b6",
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wron"
],
[
"000000000000000000000000000000000000000000000000",
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
"4975bb3d1faf5308c86a30893ee903a976296609db223fd717e227da5a813a34dc1428b71c84a787fc51f3b9f9dc28e9459f48c08bd9578e9d1b170f2d7ea506"
"4975bb3d1faf5308c86a30893ee903a976296609db223fd717e227da5a813a34dc1428b71c84a787fc51f3b9f9dc28e9459f48c08bd9578e9d1b170f2d7ea506",
"aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban agen"
],
[
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will",
"b059400ce0f55498a5527667e77048bb482ff6daa16c37b4b9e8af70c85b3f4df588004f19812a1a027c9a51e5e94259a560268e91cd10e206451a129826e740"
"b059400ce0f55498a5527667e77048bb482ff6daa16c37b4b9e8af70c85b3f4df588004f19812a1a027c9a51e5e94259a560268e91cd10e206451a129826e740",
"lega winn than year wave saus wort usef lega winn than year wave saus wort usef lega will"
],
[
"808080808080808080808080808080808080808080808080",
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always",
"04d5f77103510c41d610f7f5fb3f0badc77c377090815cee808ea5d2f264fdfabf7c7ded4be6d4c6d7cdb021ba4c777b0b7e57ca8aa6de15aeb9905dba674d66"
"04d5f77103510c41d610f7f5fb3f0badc77c377090815cee808ea5d2f264fdfabf7c7ded4be6d4c6d7cdb021ba4c777b0b7e57ca8aa6de15aeb9905dba674d66",
"lett advi cage absu amou doct acou avoi lett advi cage absu amou doct acou avoi lett alwa"
],
[
"ffffffffffffffffffffffffffffffffffffffffffffffff",
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when",
"d2911131a6dda23ac4441d1b66e2113ec6324354523acfa20899a2dcb3087849264e91f8ec5d75355f0f617be15369ffa13c3d18c8156b97cd2618ac693f759f"
"d2911131a6dda23ac4441d1b66e2113ec6324354523acfa20899a2dcb3087849264e91f8ec5d75355f0f617be15369ffa13c3d18c8156b97cd2618ac693f759f",
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when"
],
[
"0000000000000000000000000000000000000000000000000000000000000000",
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
"408b285c123836004f4b8842c89324c1f01382450c0d439af345ba7fc49acf705489c6fc77dbd4e3dc1dd8cc6bc9f043db8ada1e243c4a0eafb290d399480840"
"408b285c123836004f4b8842c89324c1f01382450c0d439af345ba7fc49acf705489c6fc77dbd4e3dc1dd8cc6bc9f043db8ada1e243c4a0eafb290d399480840",
"aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban aban art"
],
[
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title",
"761914478ebf6fe16185749372e91549361af22b386de46322cf8b1ba7e92e80c4af05196f742be1e63aab603899842ddadf4e7248d8e43870a4b6ff9bf16324"
"761914478ebf6fe16185749372e91549361af22b386de46322cf8b1ba7e92e80c4af05196f742be1e63aab603899842ddadf4e7248d8e43870a4b6ff9bf16324",
"lega winn than year wave saus wort usef lega winn than year wave saus wort usef lega winn than year wave saus wort titl"
],
[
"8080808080808080808080808080808080808080808080808080808080808080",
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless",
"848bbe19cad445e46f35fd3d1a89463583ac2b60b5eb4cfcf955731775a5d9e17a81a71613fed83f1ae27b408478fdec2bbc75b5161d1937aa7cdf4ad686ef5f"
"848bbe19cad445e46f35fd3d1a89463583ac2b60b5eb4cfcf955731775a5d9e17a81a71613fed83f1ae27b408478fdec2bbc75b5161d1937aa7cdf4ad686ef5f",
"lett advi cage absu amou doct acou avoi lett advi cage absu amou doct acou avoi lett advi cage absu amou doct acou bles"
],
[
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote",
"e28a37058c7f5112ec9e16a3437cf363a2572d70b6ceb3b6965447623d620f14d06bb321a26b33ec15fcd84a3b5ddfd5520e230c924c87aaa0d559749e044fef"
"e28a37058c7f5112ec9e16a3437cf363a2572d70b6ceb3b6965447623d620f14d06bb321a26b33ec15fcd84a3b5ddfd5520e230c924c87aaa0d559749e044fef",
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote"
],
[
"9e885d952ad362caeb4efe34a8e91bd2",
"ozone drill grab fiber curtain grace pudding thank cruise elder eight picnic",
"e2f88a043776c828063d4c3c97173944d32cf847a925b6e40b0b8bd0b4bead3ba734bdda5250d4698b310a71c9934e1a48e562315ce22bf85f89459df0e73a6c"
"e2f88a043776c828063d4c3c97173944d32cf847a925b6e40b0b8bd0b4bead3ba734bdda5250d4698b310a71c9934e1a48e562315ce22bf85f89459df0e73a6c",
"ozon dril grab fibe curt grac pudd than crui elde eigh picn"
],
[
"6610b25967cdcca9d59875f5cb50b0ea75433311869e930b",
"gravity machine north sort system female filter attitude volume fold club stay feature office ecology stable narrow fog",
"31736b4f31612ece84404c74a5d3b938a092480eb89c11b81491f1a3657eb2fe50024610fbe814df55913a87ef741020fcf076a75a29aea0aba638126ba4c8bb"
"31736b4f31612ece84404c74a5d3b938a092480eb89c11b81491f1a3657eb2fe50024610fbe814df55913a87ef741020fcf076a75a29aea0aba638126ba4c8bb",
"grav mach nort sort syst fema filt atti volu fold club stay feat offi ecol stab narr fog"
],
[
"68a79eaca2324873eacc50cb9c6eca8cc68ea5d936f98787c60c7ebc74e6ce7c",
"hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay length",
"17e4b5661796eeff8904550f8572289317ece7c1cc1316469f8f4c986c1ffd7b9f4c3aeac3e1713ffc21fa33707d09d57a2ece358d72111ef7c7658e7b33f2d5"
"17e4b5661796eeff8904550f8572289317ece7c1cc1316469f8f4c986c1ffd7b9f4c3aeac3e1713ffc21fa33707d09d57a2ece358d72111ef7c7658e7b33f2d5",
"hams diag priv dutc caus dela priv meat slid todd razo book happ fanc gosp tenn mapl dile loan word shrug infl dela leng"
],
[
"c0ba5a8e914111210f2bd131f3d5e08d",
"scheme spot photo card baby mountain device kick cradle pact join borrow",
"00e1e39a39e23735adab690d0ffbefda6cacc063b4a5fcc605de060bd370adc54c94370d966b9a3fae5ed16bd58a02224cbefca4146a083951b70be2a2ce3dcc"
"00e1e39a39e23735adab690d0ffbefda6cacc063b4a5fcc605de060bd370adc54c94370d966b9a3fae5ed16bd58a02224cbefca4146a083951b70be2a2ce3dcc",
"sche spot phot card baby moun devi kick crad pact join borr"
],
[
"6d9be1ee6ebd27a258115aad99b7317b9c8d28b6d76431c3",
"horn tenant knee talent sponsor spell gate clip pulse soap slush warm silver nephew swap uncle crack brave",
"e893fc34fa2a78ceaaea78c246b69257ad283fa538d88f3c4520beb618a2062b8ec4920ed1793fff6ad443523ed18c03da433004d0a1e9497e194621607bc9e2"
"e893fc34fa2a78ceaaea78c246b69257ad283fa538d88f3c4520beb618a2062b8ec4920ed1793fff6ad443523ed18c03da433004d0a1e9497e194621607bc9e2",
"horn tena knee tale spon spel gate clip puls soap slus warm silv neph swap uncl crac brav"
],
[
"9f6a2878b2520799a44ef18bc7df394e7061a224d2c33cd015b157d746869863",
"panda eyebrow bullet gorilla call smoke muffin taste mesh discover soft ostrich alcohol speed nation flash devote level hobby quick inner drive ghost inside",
"3e066d7dee2dbf8fcd3fe240a3975658ca118a8f6f4ca81cf99104944604b05a5090a79d99e545704b914ca0397fedb82fd00fd6a72098703709c891a065ee49"
"3e066d7dee2dbf8fcd3fe240a3975658ca118a8f6f4ca81cf99104944604b05a5090a79d99e545704b914ca0397fedb82fd00fd6a72098703709c891a065ee49",
"pand eyeb bull gori call smok muff tast mesh disc soft ostr alco spee nati flas devo leve hobb quic inne driv ghos insi"
],
[
"23db8160a31d3e0dca3688ed941adbf3",
"cat swing flag economy stadium alone churn speed unique patch report train",
"7ea73b3a398f8a71f7dde589d972b0358d3fa8b9e91317ecc544e42752b1bb251a1926b1f4c69eec0a80c0396aa0f7df29f7d73411d3106eba539f3d584fcdf8"
"7ea73b3a398f8a71f7dde589d972b0358d3fa8b9e91317ecc544e42752b1bb251a1926b1f4c69eec0a80c0396aa0f7df29f7d73411d3106eba539f3d584fcdf8",
"cat swin flag econ stad alon chur spee uniq patc repo trai"
],
[
"8197a4a47f0425faeaa69deebc05ca29c0a5b5cc76ceacc0",
"light rule cinnamon wrap drastic word pride squirrel upgrade then income fatal apart sustain crack supply proud access",
"d0ca8861283a7124515e825b7a06de8e0ad0dd5ac7888013efe6e3c300d4745bbd2c729f3355d769d23718579e7b735999a8f0b38e22b5bff45c9085af449056"
"d0ca8861283a7124515e825b7a06de8e0ad0dd5ac7888013efe6e3c300d4745bbd2c729f3355d769d23718579e7b735999a8f0b38e22b5bff45c9085af449056",
"ligh rule cinn wrap dras word prid squi upgr then inco fata apar sust crac supp prou acce"
],
[
"066dca1a2bb7e8a1db2832148ce9933eea0f3ac9548d793112d9a95c9407efad",
"all hour make first leader extend hole alien behind guard gospel lava path output census museum junior mass reopen famous sing advance salt reform",
"fc795be0c3f18c50dddb34e72179dc597d64055497ecc1e69e2e56a5409651bc139aae8070d4df0ea14d8d2a518a9a00bb1cc6e92e053fe34051f6821df9164c"
"fc795be0c3f18c50dddb34e72179dc597d64055497ecc1e69e2e56a5409651bc139aae8070d4df0ea14d8d2a518a9a00bb1cc6e92e053fe34051f6821df9164c",
"all hour make firs lead exte hole alie behi guar gosp lava path outp cens muse juni mass reop famo sing adva salt refo"
],
[
"f30f8c1da665478f49b001d94c5fc452",
"vessel ladder alter error federal sibling chat ability sun glass valve picture",
"e2d7f9a462875c1325f44f321392edc8eaafebf1547c89d72d10b41b4ee23af3fb0ab010f39f5cbea3b3aa671161b58262b6a508bcbe2d34ee272a942534d45f"
"e2d7f9a462875c1325f44f321392edc8eaafebf1547c89d72d10b41b4ee23af3fb0ab010f39f5cbea3b3aa671161b58262b6a508bcbe2d34ee272a942534d45f",
"vess ladd alte erro fede sibl chat abil sun glas valv pict"
],
[
"c10ec20dc3cd9f652c7fac2f1230f7a3c828389a14392f05",
"scissors invite lock maple supreme raw rapid void congress muscle digital elegant little brisk hair mango congress clump",
"a555426999448df9022c3afc2ed0e4aebff3a0ac37d8a395f81412e14994efc960ed168d39a80478e0467a3d5cfc134fef2767c1d3a27f18e3afeb11bfc8e6ad"
"a555426999448df9022c3afc2ed0e4aebff3a0ac37d8a395f81412e14994efc960ed168d39a80478e0467a3d5cfc134fef2767c1d3a27f18e3afeb11bfc8e6ad",
"scis invi lock mapl supr raw rapi void cong musc digi eleg litt bris hair mang cong clum"
],
[
"f585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f",
"void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold",
"b873212f885ccffbf4692afcb84bc2e55886de2dfa07d90f5c3c239abc31c0a6ce047e30fd8bf6a281e71389aa82d73df74c7bbfb3b06b4639a5cee775cccd3c"
"b873212f885ccffbf4692afcb84bc2e55886de2dfa07d90f5c3c239abc31c0a6ce047e30fd8bf6a281e71389aa82d73df74c7bbfb3b06b4639a5cee775cccd3c",
"void come effo suff camp surv warr heav shoo prim clut crus open amaz scre patr grou spac poin ten exis slus invo unfo"
]
]
}