Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions examples/wallets/new_from_password.py
Original file line number Diff line number Diff line change
@@ -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)
3 changes: 2 additions & 1 deletion tonsdk/crypto/__init__.py
Original file line number Diff line number Diff line change
@@ -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',

Expand Down
38 changes: 28 additions & 10 deletions tonsdk/crypto/_mnemonic.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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 = []

Expand All @@ -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