From 20c37b8307107a2448ec2c0bf09f4597b5bfd5e0 Mon Sep 17 00:00:00 2001 From: yehoyada Date: Fri, 4 Aug 2023 16:42:39 +0300 Subject: [PATCH] implement mnemonic_from_password --- examples/wallets/new_from_password.py | 10 +++++++ tonsdk/crypto/__init__.py | 3 ++- tonsdk/crypto/_mnemonic.py | 38 ++++++++++++++++++++------- 3 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 examples/wallets/new_from_password.py diff --git a/examples/wallets/new_from_password.py b/examples/wallets/new_from_password.py new file mode 100644 index 0000000..0552afd --- /dev/null +++ b/examples/wallets/new_from_password.py @@ -0,0 +1,10 @@ +from tonsdk.crypto import mnemonic_from_password +from tonsdk.contract.wallet import Wallets, WalletVersionEnum + + +password = "secretWalletPassword" +mnemonics = mnemonic_from_password(password, words_count=24) # Will create the same mnemonics for the same password +version = WalletVersionEnum.v3r2 +wc = 0 + +mnemonics, pub_k, priv_k, wallet = Wallets.from_mnemonics(mnemonics=mnemonics, version=version, workchain=wc) diff --git a/tonsdk/crypto/__init__.py b/tonsdk/crypto/__init__.py index 4641679..72bb1cd 100644 --- a/tonsdk/crypto/__init__.py +++ b/tonsdk/crypto/__init__.py @@ -1,8 +1,9 @@ from ._keystore import generate_new_keystore, generate_keystore_key -from ._mnemonic import mnemonic_new, mnemonic_to_wallet_key, mnemonic_is_valid +from ._mnemonic import mnemonic_new, mnemonic_to_wallet_key, mnemonic_is_valid, mnemonic_from_password from ._utils import private_key_to_public_key, verify_sign __all__ = [ 'mnemonic_new', + 'mnemonic_from_password', 'mnemonic_to_wallet_key', 'mnemonic_is_valid', diff --git a/tonsdk/crypto/_mnemonic.py b/tonsdk/crypto/_mnemonic.py index 6980a2f..6e4b74e 100644 --- a/tonsdk/crypto/_mnemonic.py +++ b/tonsdk/crypto/_mnemonic.py @@ -1,6 +1,7 @@ import hashlib import hmac -from typing import List, Optional, Tuple +from typing import List, Tuple +import random from nacl.bindings import crypto_sign_seed_keypair @@ -13,36 +14,35 @@ def mnemonic_is_valid(mnemo_words: List[str]) -> bool: return len(mnemo_words) == 24 and is_basic_seed(mnemonic_to_entropy(mnemo_words)) -def mnemonic_to_entropy(mnemo_words: List[str], password: Optional[str] = None): - # TODO: implement password +def mnemonic_to_entropy(mnemo_words: List[str]): sign = hmac.new((" ".join(mnemo_words)).encode( 'utf-8'), bytes(0), hashlib.sha512).digest() return sign -def mnemonic_to_seed(mnemo_words: List[str], seed: str, password: Optional[str] = None): - entropy = mnemonic_to_entropy(mnemo_words, password) +def mnemonic_to_seed(mnemo_words: List[str], seed: str): + entropy = mnemonic_to_entropy(mnemo_words) return hashlib.pbkdf2_hmac("sha512", entropy, seed, PBKDF_ITERATIONS) -def mnemonic_to_private_key(mnemo_words: List[str], password: Optional[str] = None) -> Tuple[bytes, bytes]: +def mnemonic_to_private_key(mnemo_words: List[str]) -> Tuple[bytes, bytes]: """ :rtype: (bytes(public_key), bytes(secret_key)) """ seed = mnemonic_to_seed( - mnemo_words, 'TON default seed'.encode('utf-8'), password) + mnemo_words, 'TON default seed'.encode('utf-8')) return crypto_sign_seed_keypair(seed[:32]) -def mnemonic_to_wallet_key(mnemo_words: List[str], password: Optional[str] = None) -> Tuple[bytes, bytes]: +def mnemonic_to_wallet_key(mnemo_words: List[str]) -> Tuple[bytes, bytes]: """ :rtype: (bytes(public_key), bytes(secret_key)) """ - _, priv_k = mnemonic_to_private_key(mnemo_words, password) + _, priv_k = mnemonic_to_private_key(mnemo_words) return crypto_sign_seed_keypair(priv_k[:32]) -def mnemonic_new(words_count: int = 24, password: Optional[str] = None) -> List[str]: +def mnemonic_new(words_count: int = 24) -> List[str]: while True: mnemo_arr = [] @@ -56,3 +56,21 @@ def mnemonic_new(words_count: int = 24, password: Optional[str] = None) -> List[ break return mnemo_arr + + +def mnemonic_from_password(password: str, words_count: int = 24) -> List[str]: + random.seed(password) + + while True: + mnemo_arr = [] + + for _ in range(words_count): + idx = random.randrange(0, len(english)) + mnemo_arr.append(english[idx]) + + if not is_basic_seed(mnemonic_to_entropy(mnemo_arr)): + continue + + break + + return mnemo_arr