Skip to content

Instantly share code, notes, and snippets.

@NicolasMugnier
Last active December 22, 2024 13:27
Show Gist options
  • Save NicolasMugnier/a71ca2183528092bfcabcd2aeb72f9fe to your computer and use it in GitHub Desktop.
Save NicolasMugnier/a71ca2183528092bfcabcd2aeb72f9fe to your computer and use it in GitHub Desktop.
Generate passphrase using bip39

BIP39 Passphrase Generation

This Gist contains implementations in JavaScript, PHP, and Python for generating BIP39 mnemonic passphrases.

Features:

  • Generation of random entropy.
  • Conversion to mnemonic words using the official list of 2048 words.
  • Support for passphrases with 12, 15, 18, 21, or 24 words.

Content:

  • bip39_gen.js: JavaScript implementation.
  • bip39_gen.php: PHP implementation.
  • bip39_gen.py: Python implementation.

For more information on BIP39, please consult the official documentation.

const crypto = require('crypto');
const fs = require('fs');
const https = require('https');
async function loadWordlist() {
const url = 'https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt';
return new Promise((resolve, reject) => {
https.get(url, (response) => {
if (response.statusCode === 200) {
let data = '';
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', () => {
resolve(data.trim().split('\n'));
});
} else {
reject(new Error(`Can not read file, HTTP code : ${response.statusCode}`));
}
}).on('error', (err) => {
reject(err);
});
});
}
function generateEntropy(bitSize = 128) {
if (![128, 160, 192, 224, 256].includes(bitSize)) {
throw new Error("Unsupported entropy size.");
}
return crypto.randomBytes(bitSize / 8);
}
function calculateChecksum(entropy) {
const hash = crypto.createHash('sha256').update(entropy).digest();
const checksumLength = (entropy.length * 8) / 32;
const checksumBits = hash[0] >> (8 - checksumLength);
return checksumBits;
}
function entropyToMnemonic(entropy, wordlist) {
const entropyBits = Array.from(entropy)
.map(byte => byte.toString(2).padStart(8, '0'))
.join('');
const checksumBits = calculateChecksum(entropy).toString(2).padStart(entropy.length * 8 / 32, '0');
const combinedBits = entropyBits + checksumBits;
const mnemonic = [];
for (let i = 0; i < combinedBits.length; i += 11) {
const index = parseInt(combinedBits.slice(i, i + 11), 2);
mnemonic.push(wordlist[index]);
}
return mnemonic.join(' ');
}
async function generateMnemonic(bitSize = 128) {
const wordlist = await loadWordlist();
const entropy = generateEntropy(bitSize);
return entropyToMnemonic(entropy, wordlist);
}
generateMnemonic(256).then((mnemonic) => {
console.log("Recovery Phrase:", mnemonic);
}).catch((error) => {
console.error("Erreur :", error.message);
});
<?php
declare(strict_types=1);
function loadWordlist(): array {
return explode("\n", file_get_contents('https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt'));
}
function generateEntropy(int $bitSize = 128): string {
if (!in_array($bitSize, [128, 160, 192, 224, 256])) {
throw new Exception("Unsupported entropy size.");
}
return random_bytes($bitSize / 8);
}
function calculateChecksum(string $entropy): int {
$hash = hash('sha256', $entropy, true);
$checksumLength = strlen($entropy) * 8 / 32;
$checksumBits = ord($hash[0]) >> (8 - $checksumLength);
return $checksumBits;
}
function entropyToMnemonic(string $entropy, array $wordlist): string {
$entropyBits = '';
foreach (str_split($entropy) as $byte) {
$entropyBits .= str_pad(decbin(ord($byte)), 8, '0', STR_PAD_LEFT);
}
$checksumBits = str_pad(decbin(calculateChecksum($entropy)), strlen($entropy) * 8 / 32, '0', STR_PAD_LEFT);
$combinedBits = $entropyBits . $checksumBits;
$mnemonic = [];
for ($i = 0; $i < strlen($combinedBits); $i += 11) {
$index = bindec(substr($combinedBits, $i, 11));
$mnemonic[] = $wordlist[$index];
}
return implode(' ', $mnemonic);
}
function generateMnemonic(int $bitSize = 128) {
$wordlist = loadWordlist();
$entropy = generateEntropy($bitSize);
return entropyToMnemonic($entropy, $wordlist);
}
$mnemonic = generateMnemonic(256);
echo "Recovery Phrase : $mnemonic\n";
import os
import hashlib
import requests
from requests import Response
url: str = 'https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt'
response: Response = requests.get(url)
if response.status_code == 200:
wordlist: list = response.text.splitlines()
else:
raise RuntimeError("Can not open bip-39 remote file.")
def generate_entropy(bits: int = 128) -> bytes:
if bits not in [128, 160, 192, 224, 256]:
raise ValueError("Unsupported entropy size.")
return os.urandom(bits // 8)
def calculate_checksum(entropy: bytes) -> int:
checksum_bits: int = len(entropy) * 8 // 32
entropy_hash: bytes = hashlib.sha256(entropy).digest()
checksum: int = int.from_bytes(entropy_hash, "big") >> (256 - checksum_bits)
return checksum
def convert_entropy_to_mnemonic(entropy: bytes) -> list:
entropy_bits: str = bin(int.from_bytes(entropy, "big"))[2:].zfill(len(entropy) * 8)
checksum_bits: str = bin(calculate_checksum(entropy))[2:].zfill(len(entropy) * 8 // 32)
combined_bits: str = entropy_bits + checksum_bits
mnemonic_words: list[str] = []
for i in range(0, len(combined_bits), 11):
word_index: int = int(combined_bits[i:i + 11], 2)
mnemonic_words.append(wordlist[word_index])
return mnemonic_words
def generate_mnemonic(bits: int = 128) -> str:
entropy: bytes = generate_entropy(bits)
mnemonic_words: list[str] = convert_entropy_to_mnemonic(entropy)
return " ".join(mnemonic_words)
mnemonic_phrase: str = generate_mnemonic(256)
print("Recovery Phrase:", mnemonic_phrase)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment