TON wallet mnemonics
Key pair
TON wallet mnemonics use asymmetric cryptography and derive Ed25519 key pairs. The private key signs wallet messages as message signatures, while the contract verifies these signatures with the public key in its account state.
Some TON ecosystem apps may use a different derivation method, eventually producing an Ed25519-conformant key pair.
The public key does not identify an address of a wallet contract, because the latter is derived from its complete initial state (StateInit) and the target workchain.
Mnemonic schemes
TON, multichain, and rotation mnemonics use the BIP-39 English word list. They have different validation and derivation rules.
| Scheme | Words | Derivation | Role |
|---|---|---|---|
| TON mnemonic | 24 | TON-specific HMAC and PBKDF2; see key derivation. | One Ed25519 key pair. |
| Multichain mnemonic | 12 or 24 | BIP-39 seed, BIP-44, and SLIP-0010 Ed25519; path m/44'/607'/{i}'. | One key pair per derivation path. |
| Rotation mnemonic | 24: two valid 12-word multichain phrases | Derive both halves separately at m/44'/607'/0'. | First half anchors the address; second half signs. |
For new wallets, a 12-word multichain phrase is recommended, while a 24-word TON phrase may also be used.
Wallet apps should not create 24-word multichain or rotation mnemonics by default. Furthermore, the rotation mnemonic is employed only by the WalletTg contract.
Multichain mnemonic derivation
Normalize the phrase and optional BIP-39 passphrase with NFKD. Use the phrase as the PBKDF2-HMAC-SHA512 password, with 2048 iterations and salt mnemonic followed by the normalized passphrase. The output is a 64-byte seed. The passphrase defaults to empty and differs from a TON password.
Derive an Ed25519 key with BIP-44 and SLIP-0010 at TON path m/44'/607'/{i}'. For instance, index 0 gives m/44'/607'/0'. Record the path and index because a different index derives a different key pair.
Some wallet apps use this path template.
The derivation-path index is separate from the wallet contract's subwalletId. A derived key can initialize different wallet contracts or subwallet IDs, producing different addresses from their StateInit and workchain.
Mnemonic import and scheme detection
Accept 12- and 24-word input. Treat a 12-word phrase as multichain.
For a 24-word phrase, check TON mnemonic validity with the supplied TON password, if applicable. Check the BIP-39 checksum for all 24 words. If the wallet supports rotation, check the BIP-39 checksum of each 12-word half.
If exactly one supported scheme matches, import with that scheme. If several match, derive and show each candidate account for user selection; do not choose silently. Reject a phrase that matches no supported scheme.
A wallet without rotation mnemonic support should reject a phrase that matches only the rotation mnemonic. Importing WalletTg also requires checking the derived signer against the active account's get_public_key() value.
Rotation mnemonic
A rotation mnemonic has two independently valid 12-word multichain halves. Derive each half separately at m/44'/607'/0'. Do not derive one seed from all 24 words.
The anchor half must come from a cryptographically secure random source. It does not rotate.
| Words | Key | Role |
|---|---|---|
| 1-12 | Anchor key | Determines the address and authorizes the first rotation. |
| 13-24 | Signing key | Signs ordinary messages; rotation replaces this key. |
Before all rotations, words 13-24 repeat words 1-12 — that is, anchor key is identical to the signing key upon deployment of the WalletTg contract. Each rotation must replace them with a new 12-word multichain phrase from a cryptographically secure random source.
The new, rotated half must be independent of the anchor and all earlier signing halves. A wallet must not derive it from an old key or set it back to the anchor.
A rotation-capable contract must keep its current signing key separate from the values that determine its address. It must accept only the stored current key for ordinary outgoing messages.
The rotation mnemonic is employed only by the WalletTg contract.
Key pair from a mnemonic
To transform a TON mnemonic phrase into a key pair, a seed is first derived using PBKDF2, and the key pair is then derived from that seed.
PBKDF2 has five input parameters: PRF, Password, Salt, c, and dkLen. Each of those parameters is assigned a concrete value.
Seed of the mnemonic is derived with PBKDF2 with these parameters:
| Parameter | Description | Value |
|---|---|---|
PRF | Pseudo-random function of two parameters | HMAC-SHA512 |
Password | Master password from which a derived key is generated | "" |
Salt | Sequence of bits, known as a cryptographic salt | "TON default seed" |
c | Number of iterations desired | 100000 |
dkLen | Desired bit-length of the derived key | 64 |
The first 32 seed bytes initialize the Ed25519 private key.
Generate a key pair
import { mnemonicNew, mnemonicToPrivateKey } from '@ton/crypto';
const mnemonic = await mnemonicNew(24);
const keyPair = await mnemonicToPrivateKey(mnemonic);
console.log(`Public key: ${keyPair.publicKey.toString('hex')}`);This example generates a TON mnemonic and prints only the public key. The same words and TON password always produce the same key pair.
Store the mnemonic securely. Never log the mnemonic or keyPair.secretKey. Use a test-only phrase for reproducible local tests.
Mnemonic validation
Require all 24 words to be in the BIP-39 English word list. Notice, that TON validity does not use the BIP-39 checksum, but the TON seed.
Following TON seed checks use entropy from the HMAC step as the PBKDF2-HMAC-SHA512 password and produce 64 bytes:
| Check | TON HMAC message | Salt | Iterations | Pass condition |
|---|---|---|---|---|
| Basic seed | Supplied password or empty | TON seed version | max(1, floor(100000 / 256)) = 390 | First byte is 0 |
| Password marker | Empty | TON fast seed version | 1 | First byte is 1 |
For a phrase without a TON password, the basic-seed check must pass with an empty password. For a password-enabled phrase, the password marker must pass and the basic-seed check must fail without the password. The basic-seed check must then pass with the supplied password. Use a TON mnemonic implementation for these checks.
Generate a mnemonic
import { mnemonicNew, mnemonicValidate } from '@ton/crypto';
const mnemonic = await mnemonicNew(24);
console.log(await mnemonicValidate(mnemonic));The example prints true for a valid phrase, not the recovery phrase. tonlib selects words from the BIP-39 list using secure random bytes. It retries until TON checks pass.
Always run a scheme detection before importing a 24-word phrase.
A 24-word TON phrase can also pass the BIP-39 checksum, but it is not a requirement. Some wallet apps reject and regenerate such candidates to avoid ambiguous imports.