Secret Key to Mnemonic
Description
Section titled “Description”This example demonstrates how to use secretKeyToMnemonic() 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
- secretKeyToMnemonic() extracts the first 32 bytes (seed portion) and converts to mnemonic
- This produces the same result as calling mnemonicFromSeed() on the seed directly
Prerequisites
Section titled “Prerequisites”- No LocalNet required
Run This Example
Section titled “Run This Example”From the repository root:
cd examplesnpm run example algo25/03-secret-key-to-mnemonic.ts/** * Example: Secret Key to Mnemonic * * This example demonstrates how to use secretKeyToMnemonic() 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 * - secretKeyToMnemonic() extracts the first 32 bytes (seed portion) and converts to mnemonic * - This produces the same result as calling mnemonicFromSeed() on the seed directly * * Prerequisites: * - No LocalNet required */
import { mnemonicFromSeed, secretKeyToMnemonic } from '@algorandfoundation/algokit-utils/algo25'import { formatHex, printHeader, printInfo, printStep, printSuccess } from '../shared/utils.js'
function main() { printHeader('Secret Key to Mnemonic Example')
// Step 1: Create a 64-byte secret key (simulating what Algorand uses) printStep(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) const secretKey = new Uint8Array(64) crypto.getRandomValues(secretKey)
printInfo(`Secret key length: ${secretKey.length} bytes`) printInfo(`Structure:`) printInfo(` Bytes 0-31 (seed): ${formatHex(secretKey.slice(0, 32))}`) printInfo(` Bytes 32-63 (public key): ${formatHex(secretKey.slice(32, 64))}`)
// Step 2: Display the secret key structure printStep(2, 'Understand the Secret Key Structure')
printInfo('Algorand secret keys are 64 bytes (512 bits):') printInfo('') printInfo(' ┌────────────────────────────────┬────────────────────────────────┐') printInfo(' │ Seed (32 bytes) │ Public Key (32 bytes) │') printInfo(' │ Bytes 0-31 │ Bytes 32-63 │') printInfo(' │ (Private key material) │ (Derived from seed) │') printInfo(' └────────────────────────────────┴────────────────────────────────┘') printInfo('') printInfo('The seed is the actual secret; the public key is appended for convenience.') printInfo('When converting to mnemonic, only the seed portion is needed.')
// Step 3: Convert secret key to mnemonic using secretKeyToMnemonic printStep(3, 'Convert Secret Key to Mnemonic using secretKeyToMnemonic()')
const mnemonicFromSecretKey = secretKeyToMnemonic(secretKey) const words = mnemonicFromSecretKey.split(' ')
printInfo(`Mnemonic has ${words.length} words`) printInfo('Mnemonic words:') // Display words in rows of 5 for readability for (let i = 0; i < words.length; i += 5) { const row = words.slice(i, i + 5) const numbered = row.map((w, j) => `${(i + j + 1).toString().padStart(2, ' ')}. ${w.padEnd(10)}`).join(' ') printInfo(` ${numbered}`) }
// Step 4: Explain what secretKeyToMnemonic does internally printStep(4, 'What secretKeyToMnemonic() Does Internally')
printInfo('secretKeyToMnemonic(secretKey) performs these steps:') printInfo(' 1. Extract the seed: secretKey.slice(0, 32)') printInfo(' 2. Call mnemonicFromSeed(seed) on the extracted 32 bytes') printInfo(' 3. Return the resulting 25-word mnemonic') printInfo('') printInfo('This is equivalent to:') printInfo(' const seed = secretKey.slice(0, 32)') printInfo(' const mnemonic = mnemonicFromSeed(seed)')
// Step 5: Compare with calling mnemonicFromSeed directly printStep(5, 'Compare with mnemonicFromSeed() on First 32 Bytes')
const seed = secretKey.slice(0, 32) const mnemonicFromSeedDirect = mnemonicFromSeed(seed)
printInfo('Method 1: secretKeyToMnemonic(64-byte secretKey)') printInfo(` Result: "${mnemonicFromSecretKey.split(' ').slice(0, 5).join(' ')}..."`) printInfo('') printInfo('Method 2: mnemonicFromSeed(secretKey.slice(0, 32))') printInfo(` Result: "${mnemonicFromSeedDirect.split(' ').slice(0, 5).join(' ')}..."`)
const mnemonicsMatch = mnemonicFromSecretKey === mnemonicFromSeedDirect printInfo('') printInfo(`Mnemonics identical: ${mnemonicsMatch ? 'Yes' : 'No'}`)
if (mnemonicsMatch) { printSuccess('Both methods produce identical mnemonics!') }
// Step 6: Demonstrate that only the seed portion matters printStep(6, 'Only the Seed Portion Affects the Mnemonic')
// Create a second secret key with the same seed but different "public key" bytes const secretKey2 = new Uint8Array(64) secretKey2.set(seed, 0) // Same seed crypto.getRandomValues(secretKey2.subarray(32)) // Different public key portion
const mnemonic1 = secretKeyToMnemonic(secretKey) const mnemonic2 = secretKeyToMnemonic(secretKey2)
printInfo('Secret Key 1 (first 8 bytes of public key):') printInfo(` ${formatHex(secretKey.slice(32, 40))}...`) printInfo('Secret Key 2 (first 8 bytes of public key):') printInfo(` ${formatHex(secretKey2.slice(32, 40))}...`) printInfo('') printInfo('Same seed, different public key bytes...') printInfo(`Mnemonic 1: "${mnemonic1.split(' ').slice(0, 3).join(' ')}..."`) printInfo(`Mnemonic 2: "${mnemonic2.split(' ').slice(0, 3).join(' ')}..."`) printInfo(`Mnemonics identical: ${mnemonic1 === mnemonic2 ? 'Yes' : 'No'}`)
if (mnemonic1 === mnemonic2) { printSuccess('The public key portion (bytes 32-63) does not affect the mnemonic.') }
// Step 7: Use cases for secretKeyToMnemonic printStep(7, 'When to Use secretKeyToMnemonic()')
printInfo('Use secretKeyToMnemonic() when you have a 64-byte Algorand secret key') printInfo('and need to convert it to a mnemonic for backup or display.') printInfo('') printInfo('Common scenarios:') printInfo(' - Exporting an account from a wallet') printInfo(' - Displaying the recovery phrase after key generation') printInfo(' - Converting keys from ed25519 libraries that output 64-byte keys') printInfo('') printInfo('Use mnemonicFromSeed() directly when you only have the 32-byte seed.')
// Step 8: Summary printStep(8, 'Summary')
printInfo('secretKeyToMnemonic() converts a 64-byte secret key to a 25-word mnemonic:') printInfo(' - Input: 64-byte Uint8Array (Algorand secret key format)') printInfo(' - Output: Space-separated string of 25 words') printInfo(' - Internally extracts bytes 0-31 (the seed portion)') printInfo(' - Produces identical result to mnemonicFromSeed(seed)') printInfo(' - Bytes 32-63 (public key portion) are ignored') printInfo('') printInfo('Relationship between functions:') printInfo(' secretKeyToMnemonic(sk) === mnemonicFromSeed(sk.slice(0, 32))')
printSuccess('Secret Key to Mnemonic example completed successfully!')}
main()Other examples in Mnemonic Utilities
Section titled “Other examples in Mnemonic Utilities”- Mnemonic from Seed
- Seed from Mnemonic
- Secret Key to Mnemonic
- Master Derivation Key Functions
- Error Handling for Mnemonic Functions