# Copyright (c) 2026 Emanuele Bellocchia
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
Module for TON seed utilities.
Reference: https://github.com/ton-org/ton-crypto/blob/master/src/mnemonic/mnemonic.ts
"""
# Imports
from bip_utils.utils.crypto.hmac import HmacSha512
from bip_utils.utils.crypto.pbkdf2 import Pbkdf2HmacSha512
class TonSeedUtilsConst:
"""Class container for TON seed utilities constants."""
# Password seed
PASSWORD_SEED_SALT_MOD: str = "TON fast seed version"
PASSWORD_SEED_PBKDF2_ROUNDS: int = 1
# Basic seed
BASIC_SEED_SALT_MOD: str = "TON seed version"
BASIC_SEED_PBKDF2_ROUNDS: int = 100000 // 256
# Private key seed
PRIV_KEY_SEED_SALT_MOD: str = "TON default seed"
PRIV_KEY_SEED_PBKDF2_ROUNDS: int = 100000
# HD key seed
HD_KEY_SEED_SALT_MOD: str = "TON HD Keys seed"
HD_KEY_SEED_PBKDF2_ROUNDS: int = 100000
# Seed length in bytes
SEED_LEN_BYTES: int = 64
class TonSeedUtils:
"""
TON seed utilities class.
It provides some utility functions for the seed generation and validation.
"""
@staticmethod
def GetEntropyBytes(mnemonic: str,
passphrase: str = "") -> bytes:
"""
Get entropy bytes from mnemonic and passphrase.
Args:
mnemonic (str or Mnemonic object): Mnemonic
passphrase (str, optional) : Passphrase (empty by default)
Returns:
bytes: Entropy bytes
"""
return HmacSha512().QuickDigest(mnemonic, passphrase)
@staticmethod
def IsBasicSeed(entropy_bytes: bytes) -> bool:
"""
Get if the entropy bytes are for a basic seed.
Args:
entropy_bytes (bytes): Entropy bytes to validate
Returns:
bool: True if the entropy bytes are for a basic seed, False otherwise
"""
seed_bytes = Pbkdf2HmacSha512().DeriveKey(entropy_bytes,
TonSeedUtilsConst.BASIC_SEED_SALT_MOD,
TonSeedUtilsConst.BASIC_SEED_PBKDF2_ROUNDS,
TonSeedUtilsConst.SEED_LEN_BYTES)
return seed_bytes[0] == 0
@staticmethod
def IsPasswordSeed(entropy_bytes: bytes) -> bool:
"""
Get if the entropy bytes are for a password seed.
Args:
entropy_bytes (bytes): Entropy bytes to validate
Returns:
bool: True if the entropy bytes are for a password seed, False otherwise
"""
seed_bytes = Pbkdf2HmacSha512().DeriveKey(entropy_bytes,
TonSeedUtilsConst.PASSWORD_SEED_SALT_MOD,
TonSeedUtilsConst.PASSWORD_SEED_PBKDF2_ROUNDS,
TonSeedUtilsConst.SEED_LEN_BYTES)
return seed_bytes[0] == 1
@classmethod
def IsPasswordNeeded(cls,
mnemonic: str) -> bool:
"""
Get if the mnemonic needs a password.
Args:
mnemonic (str): Mnemonic to check
Returns:
bool: True if the mnemonic needs a password, False otherwise
"""
# Use entropy bytes without passphrase in according to Ton source code
entropy_bytes = cls.GetEntropyBytes(mnemonic)
return cls.IsPasswordSeed(entropy_bytes) and not cls.IsBasicSeed(entropy_bytes)
@staticmethod
def GetPrivateKeySeed(entropy_bytes: bytes) -> bytes:
"""
Get the private key seed from entropy bytes.
Args:
entropy_bytes (bytes): Entropy bytes
Returns:
bytes: Private key seed bytes
"""
return Pbkdf2HmacSha512().DeriveKey(entropy_bytes,
TonSeedUtilsConst.PRIV_KEY_SEED_SALT_MOD,
TonSeedUtilsConst.PRIV_KEY_SEED_PBKDF2_ROUNDS,
TonSeedUtilsConst.SEED_LEN_BYTES)
@staticmethod
def GetHdKeySeed(entropy_bytes: bytes) -> bytes:
"""
Get the HD key seed from entropy bytes.
Args:
entropy_bytes (bytes): Entropy bytes
Returns:
bytes: HD key seed bytes
"""
return Pbkdf2HmacSha512().DeriveKey(entropy_bytes,
TonSeedUtilsConst.HD_KEY_SEED_SALT_MOD,
TonSeedUtilsConst.HD_KEY_SEED_PBKDF2_ROUNDS,
TonSeedUtilsConst.SEED_LEN_BYTES)