BIP39. Мнемонические фразы
Каждый раз, когда вы настраиваете свой криптокошелек, то вам предоставляется мнемоническая фраза из 12 (в некоторых случаях 24) слов и предлагается сохранить её в надёжном месте. Эти мнемоники в дальнейшем используются для восстановления аккаунтов и связанного с ними баланса.
Один набор мнемоник может быть использован для создания нескольких адресов. Этот метод генерации аккаунта был введен в Bitcoin Improvement Proposal (BIP) 39. Если кратко, то BIP39 определяет формулу для генерации мнемонической фразы. Затем из этой фразы генерируется сид (seed). Сид используется для создания закрытых/открытых ключей.
BIP39 был представлен как средство для создания детерминированных кошельков. Это метод создания понятный человеку мнемонической фразы — легкой для чтения и записи — из случайных данных, которая служит резервной копией для восстановления всего кошелька.
Как работает BIP39?
BIP39 работает, генерируя мнемоническую фразу — группу легко запоминающихся слов — из случайного числа, обычно от 128 до 256 бит. Чем больше бит, тем оно надежнее, но также и тем больше слов в исходной фразе.
Это удобно тем, что фразу:
1
scale interest rifle cricket coyote stumble right salad type initial rocket game
гораздо проще запомнить и воспроизвести, чем шестнадцатеричный сид:
1
ba8f63a81ba219bc8cddf20c617859cb3623e78ccd86a7dc62193bb809b85cf11ed5759325283cea01aedaf94194e633666f1a283f98a3ff77545f48d69b2e7b
Формула детерминирована, что означает что одна и та же мнемоническая фраза всего будет приведена к одному и тому же сиду. Если кошелек будет утерян, то всегда можно будет восстановить все ключи с помощью одной лишь фразы.
Генерация энтропии
Чем больше энтропия - тем более безопасна фраза, но и тем она длиннее. Для генерации фраз из 12-24 слов нужно 128-256 бит энтропии. Для примера возьмем 128 бит и 12 слов. Энтропия в hex и бинарном виде:
1
hex: 0xd28f1fd94601532cf7c82ef109b63a00
То же самое в 128 битах:
1
2
3
4
5
d 2 8 f 1 f d 9 4 6 0 1 5 3 2 c
1101 0010 1000 1111 0001 1111 1101 1001 0100 0110 0000 0001 0101 0011 0010 1100
f 7 c 8 2 e f 1 0 9 b 6 3 a 0 0
1111 0111 1100 1000 0010 1110 1111 0001 0000 1001 1011 0110 0011 1010 0000 0000
Считаем чек-сумму
checksum = first (length of entropy in bits/32) bits of SHA256 of entropy
В нашем случае длина энтропии = 128, делим на 32 = 4 бита. Берем sha256 от бинарного представления нашей энтропии. В нашем случае первые 4 бита от хэша будет 0101
. Добавляем эту чек-сумму в конец исходной энтропии:
1
110100101000111100011111110110010100011000000001010100110010110011110111110010000010111011110001000010011011011000111010000000000101
Разбиваем на группы
Далее разбиваем получившуюся последовательность на группы по 11 бит. Сейчас у нас 132 бита = 128+4. Должно получиться 12 групп по 11 бит:
1
11010010100 01111000111 11110110010 10001100000 00010101001 10010110011 11011111001 00000101110 11110001000 01001101101 10001110100 00000000101
Конвертируем каждую группу бит в десятеричное представление:
1
2
3
4
5
1684 967 1970 1120 169 1203
11010010100 01111000111 11110110010 10001100000 00010101001 10010110011
1785 46 1928 621 1140 5
11011111001 00000101110 11110001000 01001101101 10001110100 00000000101
Все десятеричные числа находятся в диапазоне от 0 до 2047. Они используются как индексы из словаря мнемоников.
Находим слова
Выбираем слова из словаря. В нашем примере с английским языком получим следующее:
1
2
3
4
5
1684 967 1970 1120 169 1203
spoon jump wagon metal benefit nose
1785 46 1928 621 1140 5
tennis alarm valve ethics model absent
Финальная фраза из 12 слов:
spoon jump wagon metal benefit nose tennis alarm valve ethics model absent
Алгоритм BIP39
- Генерируем случайное число.
- Конвертируем его в бинарное представление.
- Получаем чек-сумму от бинарного представления.
- Добавляем чек-сумму в конец исходного бинарного числа.
- Разделяем бинарную последовательность на группы по 11 бит.
- Каждая 11-битная группа соотносится со словом из предопределенного списка из 2048 слов.
- Результирующий список слов и будет мнемонической фразой.
Из мнемоники в сид
Мнемоническая фраза имеет смысл только когда из неё можно получить сид. А из сида уже вывести закрытые и открытые ключи. 512-битовый сид получается из Password-Based Key Derivation Function (PBKDF2). На вход функции подаются:
- хэш-функция (HMAC-SHA512)
- пароль (наша мнемоническая фраза)
- соль
- кол-во итераций хэш-функции (2048)
Из этого списка новое для нас - соль. Соль - возможность добавить дополнительный уровень безопасности кошелькам. Для создания соли строка "mnemonic"
объединяется с необязательной парольной фразой по вашему выбору. Если вы ее не укажете, парольной фразой по умолчанию будет пустая строка.
В PHP у нас уже есть нативная функция для работы с PBKDF2 - hash_pbkdf2. Получение сида из мнемонической фразы на PHP:
1
2
3
4
5
$mnemonic = 'spoon jump wagon metal benefit nose tennis alarm valve ethics model absent';
$salt = "mnemonic" . $passphrase;
echo "Seed: " . hash_pbkdf2("sha512", $mnemonic, $salt, 2048, 64 * 2, false) . PHP_EOL;
Для пустой парольной фразы (когда sault="mnemonic"
) получим следующий сид:
1
d0b894aaed90f6a4c3956ca342c4b48208367fcaa72c4df79fac24a1e9c1425808002acd871c69e531f91ec9c6b69c8d20f765bb36bc30e58eb0dd34d5bf5d9f
Код выше вернет нам набор из 64 байтов (512 бит) в hex формате. Далее можно из этого 512 битового сида получать множество приватных и публичных ключей.
BIP39 в PHP
Для работы с мнемоническими фразами в PHP есть библиотека bitcoin-php:
1
composer require protonlabs/bitcoin
Генерация мнемонической фразы из энтропии:
1
2
3
4
5
6
7
8
9
10
11
use BitWasp\Bitcoin\Crypto\Random\Random;
use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39Mnemonic;
use BitWasp\Bitcoin\Mnemonic\MnemonicFactory;
$random = new Random();
$entropy = $random->bytes(Bip39Mnemonic::MAX_ENTROPY_BYTE_LEN);
$bip39 = MnemonicFactory::bip39();
$mnemonic = $bip39->entropyToMnemonic($entropy);
echo "Mnemonic: " . $mnemonic . PHP_EOL;
Получаем фразу:
1
Mnemonic: spoon jump wagon metal benefit nose tennis alarm valve ethics model absent
Получение сида из этой фразы:
1
2
3
4
5
6
use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39SeedGenerator;
$mnemonic = 'spoon jump wagon metal benefit nose tennis alarm valve ethics model absent';
$seedGenerator = new Bip39SeedGenerator();
$seed = $seedGenerator->getSeed($mnemonic);
echo "Seed: " . $seed->getHex() . PHP_EOL;
Выведет следующее:
1
d0b894aaed90f6a4c3956ca342c4b48208367fcaa72c4df79fac24a1e9c1425808002acd871c69e531f91ec9c6b69c8d20f765bb36bc30e58eb0dd34d5bf5d9f
Получение энтропии из фразы:
1
2
3
4
5
use BitWasp\Bitcoin\Mnemonic\MnemonicFactory;
$bip39 = MnemonicFactory::bip39();
$entropy = $bip39->mnemonicToEntropy($mnemonic);
echo "Entropy: " . $entropy->getHex() . PHP_EOL; // Entropy: d28f1fd94601532cf7c82ef109b63a00
Проверить себя можно в онлайн Mnemonic Code Converter:
Что дальше?
BIP39 описывает, как строится сид фраза. С BIP39 связаны два других известных стандарта: BIP32 и BIP44:
- BIP32 (“Hierarchical deterministic wallets”) — предлагает фреймворк для иерархических детерминированных кошельков (HD Wallets) для Bitcoin, чтобы код кошелька мог управлять несколькими отдельными учетными записями Bitcoin с помощью одной сид фразы.
- BIP44 (“Multi-account hierarchy for deterministic wallets”) определяет ту же организационную иерархию для управления несколькими аккаунтами в детерминированных кошельках, но уже для других блокчейнов помимо Bitcoin (например Ethereum или Tron).
Вместе BIP32 и BIP44 добавляют гибкости, приватности и совместимости в HD кошельки. Таким образом HD кошельки расширяют возможности детерминированных кошельков, позволяя управлять огромным количеством ключей, все из которых получены из исходной мнемонической фразы (BIP39).