Skip to content

Secret Key to Mnemonic

← Back to Mnemonic Utilities

This example demonstrates how to use secret_key_to_mnemonic() to convert a 64-byte Algorand secret key to a 25-word mnemonic. Key concepts:

  • Algorand secret keys are 64 bytes: bytes 0-31 are the seed, bytes 32-63 are the public key
  • secret_key_to_mnemonic() extracts the first 32 bytes (seed portion) and converts to mnemonic
  • This produces the same result as calling mnemonic_from_seed() on the seed directly

No LocalNet required - pure utility function

From the repository’s examples directory:

Terminal window
cd examples
uv run python algo25/03_secret_key_to_mnemonic.py

View source on GitHub

03_secret_key_to_mnemonic.py
# ruff: noqa: N999, C901, PLR0912, PLR0915
"""
Example: Secret Key to Mnemonic
This example demonstrates how to use secret_key_to_mnemonic() to convert a
64-byte Algorand secret key to a 25-word mnemonic.
Key concepts:
- Algorand secret keys are 64 bytes: bytes 0-31 are the seed, bytes 32-63 are the public key
- secret_key_to_mnemonic() extracts the first 32 bytes (seed portion) and converts to mnemonic
- This produces the same result as calling mnemonic_from_seed() on the seed directly
No LocalNet required - pure utility function
"""
import secrets
from shared import format_hex, print_header, print_info, print_step, print_success
from algokit_algo25 import mnemonic_from_seed, secret_key_to_mnemonic
def main() -> None:
print_header("Secret Key to Mnemonic Example")
# Step 1: Create a 64-byte secret key (simulating what Algorand uses)
print_step(1, "Create a 64-byte Algorand Secret Key")
# In Algorand, the secret key is 64 bytes:
# - Bytes 0-31: The seed (private key material)
# - Bytes 32-63: The public key (derived from the seed)
secret_key = secrets.token_bytes(64)
print_info(f"Secret key length: {len(secret_key)} bytes")
print_info("Structure:")
print_info(f" Bytes 0-31 (seed): {format_hex(secret_key[:32])}")
print_info(f" Bytes 32-63 (public key): {format_hex(secret_key[32:64])}")
# Step 2: Display the secret key structure
print_step(2, "Understand the Secret Key Structure")
print_info("Algorand secret keys are 64 bytes (512 bits):")
print_info("")
print_info(" +--------------------------------+--------------------------------+")
print_info(" | Seed (32 bytes) | Public Key (32 bytes) |")
print_info(" | Bytes 0-31 | Bytes 32-63 |")
print_info(" | (Private key material) | (Derived from seed) |")
print_info(" +--------------------------------+--------------------------------+")
print_info("")
print_info("The seed is the actual secret; the public key is appended for convenience.")
print_info("When converting to mnemonic, only the seed portion is needed.")
# Step 3: Convert secret key to mnemonic using secret_key_to_mnemonic
print_step(3, "Convert Secret Key to Mnemonic using secret_key_to_mnemonic()")
mnemonic_from_secret_key = secret_key_to_mnemonic(secret_key)
words = mnemonic_from_secret_key.split(" ")
print_info(f"Mnemonic has {len(words)} words")
print_info("Mnemonic words:")
# Display words in rows of 5 for readability
for i in range(0, len(words), 5):
row = words[i : i + 5]
numbered = " ".join(f"{i + j + 1:2}. {w:<10}" for j, w in enumerate(row))
print_info(f" {numbered}")
# Step 4: Explain what secret_key_to_mnemonic does internally
print_step(4, "What secret_key_to_mnemonic() Does Internally")
print_info("secret_key_to_mnemonic(secret_key) performs these steps:")
print_info(" 1. Extract the seed: secret_key[:32]")
print_info(" 2. Call mnemonic_from_seed(seed) on the extracted 32 bytes")
print_info(" 3. Return the resulting 25-word mnemonic")
print_info("")
print_info("This is equivalent to:")
print_info(" seed = secret_key[:32]")
print_info(" mnemonic = mnemonic_from_seed(seed)")
# Step 5: Compare with calling mnemonic_from_seed directly
print_step(5, "Compare with mnemonic_from_seed() on First 32 Bytes")
seed = secret_key[:32]
mnemonic_from_seed_direct = mnemonic_from_seed(seed)
print_info("Method 1: secret_key_to_mnemonic(64-byte secret_key)")
print_info(f' Result: "{" ".join(mnemonic_from_secret_key.split(" ")[:5])}..."')
print_info("")
print_info("Method 2: mnemonic_from_seed(secret_key[:32])")
print_info(f' Result: "{" ".join(mnemonic_from_seed_direct.split(" ")[:5])}..."')
mnemonics_match = mnemonic_from_secret_key == mnemonic_from_seed_direct
print_info("")
print_info(f"Mnemonics identical: {'Yes' if mnemonics_match else 'No'}")
if mnemonics_match:
print_success("Both methods produce identical mnemonics!")
# Step 6: Demonstrate that only the seed portion matters
print_step(6, "Only the Seed Portion Affects the Mnemonic")
# Create a second secret key with the same seed but different "public key" bytes
secret_key2 = bytearray(64)
secret_key2[:32] = seed # Same seed
secret_key2[32:] = secrets.token_bytes(32) # Different public key portion
secret_key2 = bytes(secret_key2)
mnemonic1 = secret_key_to_mnemonic(secret_key)
mnemonic2 = secret_key_to_mnemonic(secret_key2)
print_info("Secret Key 1 (first 8 bytes of public key):")
print_info(f" {format_hex(secret_key[32:40])}...")
print_info("Secret Key 2 (first 8 bytes of public key):")
print_info(f" {format_hex(secret_key2[32:40])}...")
print_info("")
print_info("Same seed, different public key bytes...")
print_info(f'Mnemonic 1: "{" ".join(mnemonic1.split(" ")[:3])}..."')
print_info(f'Mnemonic 2: "{" ".join(mnemonic2.split(" ")[:3])}..."')
print_info(f"Mnemonics identical: {'Yes' if mnemonic1 == mnemonic2 else 'No'}")
if mnemonic1 == mnemonic2:
print_success("The public key portion (bytes 32-63) does not affect the mnemonic.")
# Step 7: Use cases for secret_key_to_mnemonic
print_step(7, "When to Use secret_key_to_mnemonic()")
print_info("Use secret_key_to_mnemonic() when you have a 64-byte Algorand secret key")
print_info("and need to convert it to a mnemonic for backup or display.")
print_info("")
print_info("Common scenarios:")
print_info(" - Exporting an account from a wallet")
print_info(" - Displaying the recovery phrase after key generation")
print_info(" - Converting keys from ed25519 libraries that output 64-byte keys")
print_info("")
print_info("Use mnemonic_from_seed() directly when you only have the 32-byte seed.")
# Step 8: Summary
print_step(8, "Summary")
print_info("secret_key_to_mnemonic() converts a 64-byte secret key to a 25-word mnemonic:")
print_info(" - Input: 64-byte bytes object (Algorand secret key format)")
print_info(" - Output: Space-separated string of 25 words")
print_info(" - Internally extracts bytes 0-31 (the seed portion)")
print_info(" - Produces identical result to mnemonic_from_seed(seed)")
print_info(" - Bytes 32-63 (public key portion) are ignored")
print_info("")
print_info("Relationship between functions:")
print_info(" secret_key_to_mnemonic(sk) == mnemonic_from_seed(sk[:32])")
print_success("Secret Key to Mnemonic example completed successfully!")
if __name__ == "__main__":
main()