/bip39-utils

BIP39 24-Word Mnemonic Management: Packing, Encryption, and QR Code Generation

Primary LanguagePythonMIT LicenseMIT

bip39 utils


Creating a 24-word list from the bip39 English word list, then packing it into 4 blocks and extracting them back.

How to use:

Source of the bip39 wordlist:
https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt
https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt

Prepare:

1. Install Required Python Libraries:
pip install cryptography pillow qrcode

2. Download the BIP39 English Wordlist:
wget https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt


create 24w.txt
Warning! Overwrites existing 24w.txt. Use only for generating and testing scripts.

python3 bip39_unique-wordlist.py
{
Mnemonic saved to 24w.txt:
feel top pride wet unaware combine person adjust dawn toe worry round reveal vital goddess auto task plunge credit walk penalty logic milk blur
}

Verifies that all words are in the bip39 word list and displays their positions.

python3 bip39_check.py
{
24w.txt Position: 1, BIP-39 Number: 679
24w.txt Position: 2, BIP-39 Number: 1832
24w.txt Position: 3, BIP-39 Number: 1365
24w.txt Position: 4, BIP-39 Number: 1997
...
24w.txt Position: 21, BIP-39 Number: 1301
24w.txt Position: 22, BIP-39 Number: 1053
24w.txt Position: 23, BIP-39 Number: 1125
24w.txt Position: 24, BIP-39 Number: 196
}

create 24wp.txt
python3 bip39_pack.py
{
Block: [678, 1831, 1364, 1996, 1891, 367] -> Unique Number: 24459747396551383407 -> Combined Number: 2445974739655138340701 -> Encoded Number: ec7dapccclfuxp
Block: [1306, 28, 447, 1820, 2030, 1507] -> Unique Number: 47054105335314740707 -> Combined Number: 4705410533531474070702 -> Encoded Number: rl1i4950bps4vi
Block: [1475, 1960, 801, 124, 1776, 1335] -> Unique Number: 53176963168680248631 -> Combined Number: 5317696316868024863103 -> Encoded Number: v69d38xjcax6kf
Block: [408, 1972, 1300, 1052, 1124, 195] -> Unique Number: 14734452145946566851 -> Combined Number: 1473445214594656685104 -> Encoded Number: 8myjnkvjyuv774
Packed numbers saved to 24wp.txt
}

cat 24wp.txt
{
ec7dapccclfuxp
rl1i4950bps4vi
v69d38xjcax6kf
8myjnkvjyuv774
}

The 4 blocks can be reordered as they have their order encoded.

Shows the unpacked wordlist from 24wp.txt.
python3 bip39_unpack.py
{
Encoded Number: ec7dapccclfuxp -> Combined Number: 2445974739655138340701 -> Sequence: 1 -> Unique Number: 24459747396551383407 -> Positions: [678, 1831, 1364, 1996, 1891, 367] -> Block: ['feel', 'top', 'pride', 'wet', 'unaware', 'combine']
Encoded Number: rl1i4950bps4vi -> Combined Number: 4705410533531474070702 -> Sequence: 2 -> Unique Number: 47054105335314740707 -> Positions: [1306, 28, 447, 1820, 2030, 1507] -> Block: ['person', 'adjust', 'dawn', 'toe', 'worry', 'round']
Encoded Number: v69d38xjcax6kf -> Combined Number: 5317696316868024863103 -> Sequence: 3 -> Unique Number: 53176963168680248631 -> Positions: [1475, 1960, 801, 124, 1776, 1335] -> Block: ['reveal', 'vital', 'goddess', 'auto', 'task', 'plunge']
Encoded Number: 8myjnkvjyuv774 -> Combined Number: 1473445214594656685104 -> Sequence: 4 -> Unique Number: 14734452145946566851 -> Positions: [408, 1972, 1300, 1052, 1124, 195] -> Block: ['credit', 'walk', 'penalty', 'logic', 'milk', 'blur']

Decoded 24-word mnemonic:
feel top pride wet unaware combine person adjust dawn toe worry round reveal vital goddess auto task plunge credit walk penalty logic milk blur

Original 24-word mnemonic from 24w.txt:
feel top pride wet unaware combine person adjust dawn toe worry round reveal vital goddess auto task plunge credit walk penalty logic milk blur

Success: The decoded mnemonic matches the original mnemonic.
}

Tests the algorithm for packing and unpacking.

python3 bip39_test.py 100
{
Progress: |██████████████████████████████████████████████████| 100.0% Complete

Success: All tests passed.
}

# other features
python3 bip39_pack.py --help
{
Usage: python3 bip39_pack.py [passphrase] [mode] [QR]
If no passphrase and mode are provided, the data will be saved without encryption.
Modes: GCM, CFB
Optional 'QR' parameter to generate QR codes for encrypted blocks and combined encrypted block.
}

python3 bip39_pack.py "helloworld" GCM
{
Block: [678, 1831, 1364, 1996, 1891, 367] -> Unique Number: 24459747396551383407 -> Combined Number: 2445974739655138340701 -> Encoded Number: ec7dapccclfuxp
Block: [1306, 28, 447, 1820, 2030, 1507] -> Unique Number: 47054105335314740707 -> Combined Number: 4705410533531474070702 -> Encoded Number: rl1i4950bps4vi
Block: [1475, 1960, 801, 124, 1776, 1335] -> Unique Number: 53176963168680248631 -> Combined Number: 5317696316868024863103 -> Encoded Number: v69d38xjcax6kf
Block: [408, 1972, 1300, 1052, 1124, 195] -> Unique Number: 14734452145946566851 -> Combined Number: 1473445214594656685104 -> Encoded Number: 8myjnkvjyuv774

Encrypted Blocks:
Encrypted block 1: R0NNOiKGGN_cUphOBc9HmKLORYI07PkZ2ywvcbJ8szUoZrvvBnKMXAOcKf6UrVNry4-E61KdHR3jgMceG7U=
Encrypted block 2: R0NNOuSTLk_PXcxeqhOdNje4eq34-wYNSl_sTFv-dhZnwxLVb9GtR4tgcW8SPbaLzo5AiYT54zS97XKUIIg=
Encrypted block 3: R0NNOgtpfNXAbNQXc9xWnKIkH6rS5m_8IRd9IscJESrSySpo2T2SjKpLp5Eeif7-UK9Nq0TSpZIxU3-CeVU=
Encrypted block 4: R0NNOhpnK7vCscdDDVgBzIto70lCe9j1xog761FEBX5FaRlw7S4DlomlMX-2iEA0AknRLOGJAqY--7e0LvM=

Combined Encrypted Block:
R0NNOgxcpak4t1RRZnF_Qn8ahrig-2KrVY98ubD81HHGtk96kEYsoi8ZMvmlezA9lo_kh1scdrS1sZj_LbNPUxh0faxiYuUNCcY7E3tVX8AGWee6pBuPojVpyrzUaTSsiQaeU9v1fgN17AU=
}

# decrypt
python3 bip39_unpack.py --help
{
Usage: python3 bip39_unpack.py [passphrase] [encrypted_data]
If no passphrase and encrypted data are provided, the data will be read without decryption.
Modes: GCM, CFB
}

python3 bip39_unpack.py "helloworld" R0NNOkHVzaE4vXDAB9FrovI7FzwehDvz7F33vXQJTUj22iKu6TBZe__k-5G8zpm2oPF51rRMfdfGwGv_hZxtPT3KTAAEkXBxEjGE8G1bs1yYRHWSH0R71lPOZXPyJ7yXN9eXx_GktrW60eE=
{
Decrypted data: ec7dapccclfuxp
rl1i4950bps4vi
v69d38xjcax6kf
8myjnkvjyuv774
Encoded Number: ec7dapccclfuxp -> Combined Number: 2445974739655138340701 -> Sequence: 1 -> Unique Number: 24459747396551383407 -> Positions: [678, 1831, 1364, 1996, 1891, 367] -> Block: ['feel', 'top', 'pride', 'wet', 'unaware', 'combine']
Encoded Number: rl1i4950bps4vi -> Combined Number: 4705410533531474070702 -> Sequence: 2 -> Unique Number: 47054105335314740707 -> Positions: [1306, 28, 447, 1820, 2030, 1507] -> Block: ['person', 'adjust', 'dawn', 'toe', 'worry', 'round']
Encoded Number: v69d38xjcax6kf -> Combined Number: 5317696316868024863103 -> Sequence: 3 -> Unique Number: 53176963168680248631 -> Positions: [1475, 1960, 801, 124, 1776, 1335] -> Block: ['reveal', 'vital', 'goddess', 'auto', 'task', 'plunge']
Encoded Number: 8myjnkvjyuv774 -> Combined Number: 1473445214594656685104 -> Sequence: 4 -> Unique Number: 14734452145946566851 -> Positions: [408, 1972, 1300, 1052, 1124, 195] -> Block: ['credit', 'walk', 'penalty', 'logic', 'milk', 'blur']

Decoded 24-word mnemonic:
feel top pride wet unaware combine person adjust dawn toe worry round reveal vital goddess auto task plunge credit walk penalty logic milk blur

Original 24-word mnemonic from 24w.txt:
feel top pride wet unaware combine person adjust dawn toe worry round reveal vital goddess auto task plunge credit walk penalty logic milk blur

Success: The decoded mnemonic matches the original mnemonic.
}

# sequential block decrypt
python3 bip39_unpack.py "helloworld" R0NNOm5T1y8Osi1GcJWuvmIm36NSgUBGd8mbypkeMvRHbawY5TaDooOF3l4Gk6retwKfoYaKRz7-wTqdlYI=
{
Decrypted data: v69d38xjcax6kf
Encoded Number: v69d38xjcax6kf -> Combined Number: 5317696316868024863103 -> Sequence: 3 -> Unique Number: 53176963168680248631 -> Positions: [1475, 1960, 801, 124, 1776, 1335] -> Block: ['reveal', 'vital', 'goddess', 'auto', 'task', 'plunge']

Decoded block corresponding to sequence number:
Sequence: 3, Block: ['13 reveal', '14 vital', '15 goddess', '16 auto', '17 task', '18 plunge'], Positions: [1475, 1960, 801, 124, 1776, 1335]

Success: The decoded block matches the original mnemonic block.
}

QR codes are generated only when encryption is used.

python3 bip39_pack.py "helloworld" GCM QR
{
Block: [678, 1831, 1364, 1996, 1891, 367] -> Unique Number: 24459747396551383407 -> Combined Number: 2445974739655138340701 -> Encoded Number: ec7dapccclfuxp
Block: [1306, 28, 447, 1820, 2030, 1507] -> Unique Number: 47054105335314740707 -> Combined Number: 4705410533531474070702 -> Encoded Number: rl1i4950bps4vi
Block: [1475, 1960, 801, 124, 1776, 1335] -> Unique Number: 53176963168680248631 -> Combined Number: 5317696316868024863103 -> Encoded Number: v69d38xjcax6kf
Block: [408, 1972, 1300, 1052, 1124, 195] -> Unique Number: 14734452145946566851 -> Combined Number: 1473445214594656685104 -> Encoded Number: 8myjnkvjyuv774

Encrypted Blocks:
Encrypted block 1: R0NNOr41805UKGdwgQvppvxgBrUz2d9VDXRNd66_QiZPFlpSDW8_9IOKH0Srjz0p5ixu2PwY2YmZLWyO-3Y=
QR code for block 1 generated as block_1_qr.png
Encrypted block 2: R0NNOn4zYIIXxb3BWvUxfQcXPTUKnaTA-nx65cDc0UF733YCB8iMbCVTInqxaN1swTg9Sio9POWUSXpHf-o=
QR code for block 2 generated as block_2_qr.png
Encrypted block 3: R0NNOsumD5uNvT1WTnQ1HGk7Vpw9vW9fVd9DN63pwC9ILciuNwXp0dqhZFpwQ8fwV657MuXYs8VOER7BW8k=
QR code for block 3 generated as block_3_qr.png
Encrypted block 4: R0NNOhIm7KLFbOnHoQw6qT2UHbjAXtrpIKRZdtMvNGkP5VsgoJG8iYdavgzAM0DXt2NC9pqImKcd083gWyc=
QR code for block 4 generated as block_4_qr.png

Combined Encrypted Block:
R0NNOgsRelsuhWKtUa5xP_ExAbpQWIqklB9vq3nVWkE-neFL6j1HMIJErNj61YzfggWXL5UObvl_JRQV2mp6Ij0GUh2i9thhGA971R83m8YO7DE_dXCWlQqvvzU7J_BI-m_3fvmy6od4dls=
Combined QR code generated as combined_qr.png
}

block_1_qr.pngblock_2_qr.pngblock_3_qr.pngblock_4_qr.png
combined_qr.png

For completeness, but using these scripts might not be a good idea. Use at your own risk! Highly experimental!