Master Key Export
Description
Section titled “Description”This example demonstrates how to export the master derivation key (MDK) for wallet backup using the KMD exportMasterKey() method.
Key concepts:
- The master derivation key (MDK) is the root key used to deterministically generate all keys in the wallet
- With the MDK, you can recreate a wallet and regenerate all derived keys
- Imported keys CANNOT be recovered from the MDK
- The MDK should be stored securely as it can regenerate all wallet keys
Prerequisites
Section titled “Prerequisites”- LocalNet running (via
algokit localnet start) - Covered operations:
- exportMasterKey() - Export the master derivation key from a wallet
Run This Example
Section titled “Run This Example”From the repository root:
cd examplesnpm run example kmd_client/07-master-key-export.ts/** * Example: Master Key Export * * This example demonstrates how to export the master derivation key (MDK) * for wallet backup using the KMD `exportMasterKey()` method. * * Key concepts: * - The master derivation key (MDK) is the root key used to deterministically * generate all keys in the wallet * - With the MDK, you can recreate a wallet and regenerate all derived keys * - Imported keys CANNOT be recovered from the MDK * - The MDK should be stored securely as it can regenerate all wallet keys * * Prerequisites: * - LocalNet running (via `algokit localnet start`) * * Covered operations: * - exportMasterKey() - Export the master derivation key from a wallet */
import { cleanupTestWallet, createKmdClient, createTestWallet, printError, printHeader, printInfo, printStep, printSuccess,} from '../shared/utils.js'
/** * Format a byte array for display, showing first and last few bytes for security */function formatBytesForDisplay(bytes: Uint8Array, showFirst = 4, showLast = 4): string { const hex = Buffer.from(bytes).toString('hex') if (bytes.length <= showFirst + showLast) { return hex } const firstBytes = hex.slice(0, showFirst * 2) const lastBytes = hex.slice(-(showLast * 2)) return `${firstBytes}...${lastBytes}`}
async function main() { printHeader('KMD Master Key Export Example')
const kmd = createKmdClient() let walletHandleToken = '' const walletPassword = 'test-password'
try { // ========================================================================= // Step 1: Create a Test Wallet // ========================================================================= printStep(1, 'Creating a test wallet')
const testWallet = await createTestWallet(kmd, walletPassword) walletHandleToken = testWallet.walletHandleToken
printSuccess(`Test wallet created: ${testWallet.walletName}`) printInfo(`Wallet ID: ${testWallet.walletId}`)
// ========================================================================= // Step 2: Generate Several Keys in the Wallet // ========================================================================= printStep(2, 'Generating several keys in the wallet')
const generatedAddresses: string[] = [] const numKeys = 3
for (let i = 1; i <= numKeys; i++) { const result = await kmd.generateKey({ walletHandleToken }) generatedAddresses.push(result.address.toString()) printInfo(`Key ${i}: ${result.address}`) }
printSuccess(`Generated ${numKeys} keys in the wallet`) printInfo('') printInfo('These keys are deterministically derived from the master derivation key.') printInfo('They can be regenerated by creating a new wallet with the same MDK.')
// ========================================================================= // Step 3: Export the Master Derivation Key // ========================================================================= printStep(3, 'Exporting the master derivation key with exportMasterKey()')
const exportResult = await kmd.exportMasterKey({ walletHandleToken, walletPassword, })
const masterKey = exportResult.masterDerivationKey
printSuccess('Master derivation key exported successfully!') printInfo('') printInfo('ExportMasterKeyResponse fields:') printInfo(` masterDerivationKey (${masterKey.length} bytes): ${formatBytesForDisplay(masterKey)}`) printInfo('') printInfo('Note: The wallet password is required to export the master key for security.')
// ========================================================================= // Step 4: Explain What the Master Key Is // ========================================================================= printStep(4, 'Understanding the master derivation key')
printInfo('') printInfo('What is the Master Derivation Key (MDK)?') printInfo('-'.repeat(40)) printInfo('') printInfo('The MDK is the cryptographic root of your wallet. It is used to:') printInfo('') printInfo(' 1. BACKUP/RECOVERY: Store this key to recover your wallet') printInfo(' - Create a new wallet with the MDK to restore it') printInfo(' - Call generateKey() the same number of times to recover keys') printInfo(` - In this example, calling generateKey() ${numKeys} times would`) printInfo(' regenerate the exact same addresses') printInfo('') printInfo(' 2. DETERMINISTIC DERIVATION: Keys are derived in sequence') printInfo(' - First generateKey() call always produces the same address') printInfo(' - Second call produces the same second address, etc.') printInfo(' - This sequence is reproducible with the same MDK')
// ========================================================================= // Step 5: Important Limitations // ========================================================================= printStep(5, 'Important limitations - Imported keys')
printInfo('') printInfo('IMPORTANT: Imported keys CANNOT be recovered from the MDK!') printInfo('-'.repeat(40)) printInfo('') printInfo('The MDK only protects keys generated with generateKey().') printInfo('') printInfo('Keys imported with importKey():') printInfo(' - Are stored in the wallet database') printInfo(' - Can be used for transactions while the wallet exists') printInfo(' - CANNOT be regenerated from the MDK') printInfo(' - Must be backed up separately using exportKey()') printInfo('') printInfo('To fully backup a wallet with imported keys:') printInfo(' 1. Export and store the MDK (for generated keys)') printInfo(' 2. Export and store each imported key separately') printInfo(' 3. Or backup the entire wallet database file')
// ========================================================================= // Step 6: Security Implications // ========================================================================= printStep(6, 'Security implications')
printInfo('') printInfo('⚠️ SECURITY WARNING: Handle the MDK with extreme care!') printInfo('-'.repeat(40)) printInfo('') printInfo('Anyone with access to your MDK can:') printInfo(' - Recreate your entire wallet') printInfo(' - Generate all your derived keys') printInfo(' - Sign transactions and move your funds') printInfo('') printInfo('Best practices for MDK storage:') printInfo(' - Never store it in plain text on your computer') printInfo(' - Use hardware security modules (HSM) for production') printInfo(' - Consider splitting the key using Shamir Secret Sharing') printInfo(' - Store backups in secure, offline locations') printInfo(' - Never transmit the MDK over insecure channels') printInfo('') printInfo('The MDK in this example is for demonstration only.') printInfo('In production, implement proper key management practices.')
// ========================================================================= // Step 7: Verify Keys Can Be Listed // ========================================================================= printStep(7, 'Verifying wallet state')
const listResult = await kmd.listKeysInWallet({ walletHandleToken })
printSuccess(`Wallet contains ${listResult.addresses.length} key(s)`) printInfo('') printInfo('Generated addresses (would be recoverable from MDK):') listResult.addresses.forEach((addr, i) => { printInfo(` ${i + 1}. ${addr}`) })
// ========================================================================= // Cleanup // ========================================================================= printStep(8, 'Cleaning up test wallet')
await cleanupTestWallet(kmd, walletHandleToken) walletHandleToken = '' // Mark as cleaned up
printSuccess('Test wallet handle released')
// ========================================================================= // Summary // ========================================================================= printHeader('Summary') printInfo('This example demonstrated master key export in KMD:') printInfo('') printInfo(' exportMasterKey()') printInfo(' Parameters: walletHandleToken, walletPassword') printInfo(` Returns: masterDerivationKey (${masterKey.length}-byte Uint8Array)`) printInfo('') printInfo('Key takeaways:') printInfo(' - The MDK is the root key for deterministic key derivation') printInfo(` - MDK is ${masterKey.length} bytes (256 bits) for ed25519`) printInfo(' - Wallet password is required to export the MDK') printInfo(' - Generated keys can be recovered with the MDK') printInfo(' - Imported keys CANNOT be recovered with the MDK') printInfo(' - The MDK must be stored securely - it controls all funds!') printInfo('') printInfo('Note: The test wallet remains in KMD (wallets cannot be deleted via API).') } catch (error) { printError(`Error: ${error instanceof Error ? error.message : String(error)}`) printInfo('') printInfo('Troubleshooting:') printInfo(' - Ensure LocalNet is running: algokit localnet start') printInfo(' - If LocalNet issues occur: algokit localnet reset') printInfo(' - Check that KMD is accessible on port 4002')
// Cleanup on error if (walletHandleToken) { await cleanupTestWallet(kmd, walletHandleToken) }
process.exit(1) }}
main().catch((error) => { console.error('Fatal error:', error) process.exit(1)})Other examples in KMD Client
Section titled “Other examples in KMD Client”- KMD Version Information
- Wallet Creation and Listing
- Wallet Session Management
- Key Generation
- Key Import and Export
- Key Listing and Deletion
- Master Key Export
- Multisig Account Setup
- Multisig Account Management
- Transaction Signing with KMD
- Multisig Transaction Signing with KMD
- Program Signing (Delegated Logic Signatures) with KMD
- Multisig Program Signing (Delegated Multisig Logic Signatures) with KMD