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