Secure, audited & minimal implementation of BIP39 mnemonic phrases
npx @tessl/cli install tessl/npm-scure--bip39@2.0.0@scure/bip39 is a secure, audited, and minimal implementation of BIP39 mnemonic phrases for cryptocurrency applications. It provides comprehensive functionality for generating cryptographically secure mnemonic phrases, converting between mnemonics and entropy, validating mnemonic phrases, and deriving seed data using key derivation functions.
npm install @scure/bip39import * as bip39 from '@scure/bip39';
import { wordlist } from '@scure/bip39/wordlists/english.js';For CommonJS:
const bip39 = require('@scure/bip39');
const { wordlist } = require('@scure/bip39/wordlists/english.js');import * as bip39 from '@scure/bip39';
import { wordlist } from '@scure/bip39/wordlists/english.js';
// Generate a random 12-word mnemonic
const mnemonic = bip39.generateMnemonic(wordlist);
console.log(mnemonic);
// "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
// Validate the mnemonic
const isValid = bip39.validateMnemonic(mnemonic, wordlist);
console.log(isValid); // true
// Convert mnemonic to seed for cryptographic operations
const seed = await bip39.mnemonicToSeed(mnemonic, 'optional-passphrase');
console.log(seed); // Uint8Array(64) [...]
// Convert mnemonic to raw entropy (reversible)
const entropy = bip39.mnemonicToEntropy(mnemonic, wordlist);
// Convert entropy back to mnemonic (reversible)
const recreatedMnemonic = bip39.entropyToMnemonic(entropy, wordlist);@scure/bip39 is built around several key components:
Generate cryptographically secure random mnemonic phrases using CSPRNG.
/**
* Generate x random words. Uses Cryptographically-Secure Random Number Generator.
* @param wordlist - Array of 2048 words for specific language
* @param strength - Mnemonic strength in bits: 128, 160, 192, 224, or 256 (default: 128)
* @returns Mnemonic string with 12, 15, 18, 21, or 24 words respectively
* @throws TypeError for invalid entropy strength (must be divisible by 32 and ≤256)
*/
function generateMnemonic(wordlist: string[], strength: number = 128): string;Usage Examples:
import { generateMnemonic } from '@scure/bip39';
import { wordlist } from '@scure/bip39/wordlists/english.js';
// Generate 12-word mnemonic (128 bits, default)
const mnemonic12 = generateMnemonic(wordlist);
// Generate 24-word mnemonic (256 bits)
const mnemonic24 = generateMnemonic(wordlist, 256);
// Generate 15-word mnemonic (160 bits)
const mnemonic15 = generateMnemonic(wordlist, 160);
// Generate 18-word mnemonic (192 bits)
const mnemonic18 = generateMnemonic(wordlist, 192);
// Generate 21-word mnemonic (224 bits)
const mnemonic21 = generateMnemonic(wordlist, 224);Convert between mnemonic strings and raw entropy bytes (bidirectional operations).
/**
* Reversible: Converts mnemonic string to raw entropy in form of byte array.
* @param mnemonic - 12-24 word mnemonic string
* @param wordlist - Wordlist array used for mnemonic
* @returns Uint8Array of entropy bytes
* @throws Error for invalid mnemonic or entropy length
*/
function mnemonicToEntropy(mnemonic: string, wordlist: string[]): Uint8Array;
/**
* Reversible: Converts raw entropy in form of byte array to mnemonic string.
* @param entropy - Uint8Array of entropy bytes (16, 20, 24, 28, or 32 bytes)
* @param wordlist - Wordlist array for mnemonic generation
* @returns 12-24 word mnemonic string
*/
function entropyToMnemonic(entropy: Uint8Array, wordlist: string[]): string;Usage Examples:
import { mnemonicToEntropy, entropyToMnemonic } from '@scure/bip39';
import { wordlist } from '@scure/bip39/wordlists/english.js';
const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
// Convert mnemonic to entropy
const entropy = mnemonicToEntropy(mnemonic, wordlist);
console.log(entropy); // Uint8Array(16) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
// Convert entropy back to mnemonic
const recreatedMnemonic = entropyToMnemonic(entropy, wordlist);
console.log(recreatedMnemonic === mnemonic); // true
// Using custom entropy
const customEntropy = new Uint8Array([
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
]);
const customMnemonic = entropyToMnemonic(customEntropy, wordlist);Validate mnemonic phrases against specific wordlists.
/**
* Validates mnemonic for being 12-24 words contained in wordlist.
* @param mnemonic - Mnemonic string to validate
* @param wordlist - Wordlist array for validation
* @returns Boolean indicating validity
*/
function validateMnemonic(mnemonic: string, wordlist: string[]): boolean;Usage Examples:
import { validateMnemonic } from '@scure/bip39';
import { wordlist } from '@scure/bip39/wordlists/english.js';
const validMnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
const invalidMnemonic = 'invalid mnemonic phrase';
console.log(validateMnemonic(validMnemonic, wordlist)); // true
console.log(validateMnemonic(invalidMnemonic, wordlist)); // false
// Validate against different language
import { wordlist as frenchWordlist } from '@scure/bip39/wordlists/french.js';
console.log(validateMnemonic(validMnemonic, frenchWordlist)); // false (wrong language)Derive cryptographic seeds from mnemonic phrases using PBKDF2 with optional passphrase protection.
/**
* Derive 64-byte seed from mnemonic using PBKDF2-SHA512 with 2048 iterations (async, irreversible)
* @param mnemonic - 12-24 word mnemonic string
* @param passphrase - Optional password for additional protection (default: '')
* @returns Promise resolving to 64-byte Uint8Array seed
*/
function mnemonicToSeed(mnemonic: string, passphrase: string = ''): Promise<Uint8Array>;
/**
* Derive 64-byte seed from mnemonic using PBKDF2-SHA512 with 2048 iterations (sync, irreversible)
* @param mnemonic - 12-24 word mnemonic string
* @param passphrase - Optional password for additional protection (default: '')
* @returns 64-byte Uint8Array seed
*/
function mnemonicToSeedSync(mnemonic: string, passphrase: string = ''): Uint8Array;
/**
* Derive 64-byte seed using native WebCrypto API with PBKDF2-SHA512 and 2048 iterations (async, irreversible)
* @param mnemonic - 12-24 word mnemonic string
* @param passphrase - Optional password for additional protection (default: '')
* @returns Promise resolving to 64-byte Uint8Array seed
*/
function mnemonicToSeedWebcrypto(mnemonic: string, passphrase: string = ''): Promise<Uint8Array>;Usage Examples:
import { mnemonicToSeed, mnemonicToSeedSync, mnemonicToSeedWebcrypto } from '@scure/bip39';
const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
// Async version (recommended)
const seed = await mnemonicToSeed(mnemonic);
console.log(seed.length); // 64
// With passphrase for additional security
const seedWithPass = await mnemonicToSeed(mnemonic, 'my-secret-passphrase');
// Synchronous version (blocks execution)
const seedSync = mnemonicToSeedSync(mnemonic);
// WebCrypto version (faster in browsers)
const seedWebcrypto = await mnemonicToSeedWebcrypto(mnemonic, 'passphrase');@scure/bip39 supports 10 different language wordlists, each containing exactly 2048 words.
// All wordlist modules export the same interface
interface WordlistModule {
wordlist: string[];
}Available Wordlists:
// English (most commonly used)
import { wordlist } from '@scure/bip39/wordlists/english.js';
// Other supported languages
import { wordlist as czech } from '@scure/bip39/wordlists/czech.js';
import { wordlist as french } from '@scure/bip39/wordlists/french.js';
import { wordlist as italian } from '@scure/bip39/wordlists/italian.js';
import { wordlist as japanese } from '@scure/bip39/wordlists/japanese.js';
import { wordlist as korean } from '@scure/bip39/wordlists/korean.js';
import { wordlist as portuguese } from '@scure/bip39/wordlists/portuguese.js';
import { wordlist as simplifiedChinese } from '@scure/bip39/wordlists/simplified-chinese.js';
import { wordlist as spanish } from '@scure/bip39/wordlists/spanish.js';
import { wordlist as traditionalChinese } from '@scure/bip39/wordlists/traditional-chinese.js';Usage Examples:
import { generateMnemonic, validateMnemonic } from '@scure/bip39';
import { wordlist as english } from '@scure/bip39/wordlists/english.js';
import { wordlist as japanese } from '@scure/bip39/wordlists/japanese.js';
// Generate English mnemonic
const englishMnemonic = generateMnemonic(english);
// Generate Japanese mnemonic (uses ideographic space U+3000 as separator instead of regular space)
const japaneseMnemonic = generateMnemonic(japanese);
console.log(japaneseMnemonic); // Words separated by (U+3000) instead of space
// Validate against specific language
const isValidEnglish = validateMnemonic(englishMnemonic, english);
const isValidJapanese = validateMnemonic(japaneseMnemonic, japanese);
// Cross-language validation will fail
const crossValidation = validateMnemonic(englishMnemonic, japanese); // false// All wordlists are arrays of exactly 2048 strings
type Wordlist = string[];
// Entropy byte arrays must be exactly 16, 20, 24, 28, or 32 bytes
// corresponding to 128, 160, 192, 224, or 256 bits respectively
type EntropyBytes = Uint8Array;
// Mnemonic strength must be exactly 128, 160, 192, 224, or 256 bits
// corresponding to 12, 15, 18, 21, or 24 words respectively
type MnemonicStrength = 128 | 160 | 192 | 224 | 256;
// Seed is always 64 bytes
type Seed = Uint8Array;The library throws specific errors for various invalid inputs:
@noble/hashesmnemonicToSeedWebcrypto uses native browser APIs for better performance