UNPKG

meta-log-db

Version:

Native database package for Meta-Log (ProLog, DataLog, R5RS)

140 lines 5.12 kB
"use strict"; /** * BIP39 Mnemonic Implementation * * Implements mnemonic phrase generation and validation using Web Crypto API * Based on BIP39 specification: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki * * Note: This is a simplified implementation. Full BIP39 requires: * - Word list (2048 words) * - Checksum validation * - Proper entropy generation */ Object.defineProperty(exports, "__esModule", { value: true }); exports.generateMnemonic = generateMnemonic; exports.validateMnemonic = validateMnemonic; exports.mnemonicToSeed = mnemonicToSeed; exports.seedToMnemonic = seedToMnemonic; /** * BIP39 word list (first 100 words as example - full list has 2048 words) * Full implementation should include all 2048 words from BIP39 specification */ const BIP39_WORDLIST = [ 'abandon', 'ability', 'able', 'about', 'above', 'absent', 'absorb', 'abstract', 'absurd', 'abuse', 'access', 'accident', 'account', 'accuse', 'achieve', 'acid', 'acoustic', 'acquire', 'across', 'act', 'action', 'actor', 'actual', 'adapt', 'add', 'addict', 'address', 'adjust', 'admit', 'adult', 'advance', 'advice', 'aerobic', 'affair', 'afford', 'afraid', 'again', 'age', 'agent', 'agree', 'ahead', 'aim', 'air', 'airport', 'aisle', 'alarm', 'album', 'alcohol', 'alert', 'alien', 'all', 'alley', 'allow', 'almost', 'alone', 'alpha', 'already', 'also', 'alter', 'always', 'amateur', 'amazing', 'among', 'amount', 'amused', 'analyst', 'anchor', 'ancient', 'anger', 'angle', 'angry', 'animal', 'ankle', 'announce', 'annual', 'another', 'answer', 'antenna', 'antique', 'anxiety', 'any', 'apart', 'apology', 'appear', 'apple', 'approve', 'april', 'area', 'arena', 'argue', 'arm', 'armed', 'armor', 'army', 'around', 'arrange' ]; /** * Generate random entropy using Web Crypto API */ async function generateEntropy(bits) { const bytes = bits / 8; const entropy = new Uint8Array(bytes); crypto.getRandomValues(entropy); return entropy; } /** * Calculate checksum from entropy */ function calculateChecksum(entropy) { // Simplified checksum: sum of all bytes modulo 256 // Full implementation would use SHA256 hash and take first bits let sum = 0; for (const byte of entropy) { sum += byte; } return sum % 256; } /** * Convert entropy to mnemonic words */ function entropyToMnemonic(entropy) { const words = []; const checksum = calculateChecksum(entropy); // Combine entropy with checksum const combined = new Uint8Array(entropy.length + 1); combined.set(entropy, 0); combined[entropy.length] = checksum; // Convert to words (simplified - full implementation uses 11-bit indices) for (let i = 0; i < combined.length; i++) { const index = combined[i] % BIP39_WORDLIST.length; words.push(BIP39_WORDLIST[index]); } return words.join(' '); } /** * Generate BIP39 mnemonic phrase * * @param strength - Entropy strength in bits (128, 160, 192, 224, or 256) * @returns Mnemonic phrase (space-separated words) */ async function generateMnemonic(strength = 256) { if (![128, 160, 192, 224, 256].includes(strength)) { throw new Error('Strength must be 128, 160, 192, 224, or 256'); } const entropy = await generateEntropy(strength); return entropyToMnemonic(entropy); } /** * Validate mnemonic phrase * * @param mnemonic - Mnemonic phrase to validate * @returns true if valid, false otherwise */ function validateMnemonic(mnemonic) { const words = mnemonic.trim().split(/\s+/); // Check word count (should be 12, 15, 18, 21, or 24 words) if (![12, 15, 18, 21, 24].includes(words.length)) { return false; } // Check all words are in wordlist for (const word of words) { if (!BIP39_WORDLIST.includes(word.toLowerCase())) { return false; } } // Validate checksum (simplified) return true; } /** * Convert mnemonic to seed using PBKDF2 * * @param mnemonic - Mnemonic phrase * @param passphrase - Optional passphrase (default: empty string) * @returns Seed bytes (64 bytes) */ async function mnemonicToSeed(mnemonic, passphrase = '') { if (!validateMnemonic(mnemonic)) { throw new Error('Invalid mnemonic phrase'); } const mnemonicBytes = new TextEncoder().encode(mnemonic.normalize('NFKD')); const saltBytes = new TextEncoder().encode(`mnemonic${passphrase}`.normalize('NFKD')); // Import mnemonic as key material const keyMaterial = await crypto.subtle.importKey('raw', mnemonicBytes, { name: 'PBKDF2' }, false, ['deriveBits']); // Derive seed using PBKDF2 const seedBits = await crypto.subtle.deriveBits({ name: 'PBKDF2', salt: saltBytes, iterations: 2048, hash: 'SHA-512' }, keyMaterial, 512 // 64 bytes = 512 bits ); return new Uint8Array(seedBits); } /** * Convert seed to mnemonic (reverse operation - not standard BIP39) * This is a helper for testing/debugging */ function seedToMnemonic(seed) { return entropyToMnemonic(seed); } //# sourceMappingURL=bip39.js.map