Title: webtricks: SEED и получение адресов биткойна Post by: XEOP$ on February 22, 2021, 04:49:21 PM Замечу, что webtricks иногда вносит правки в свою статью, которые будут отслеживаться мною в этой теме.
Обзор работы Seed Phrase & The Process of Deriving Bitcoin Addresses from It (https://bitcointalk.org/index.php?topic=5316005) Автор: webtricks (https://bitcointalk.org/index.php?action=profile;u=921974)Рассматриваемая работа под авторством webtricks посвящена иерархически детерминированным кошелькам биткойна. Ее автор напоминает всем, что первые кошельки для биткойна можно было представлять себе как группу приватных ключей. Отсюда следовало то , что при генерации новых ключей пользователю приходилось сталкиваться с громоздким и обременительным процессом, подразумевающим под собой создание резервной копии каждого приватного ключа. С появленим иерархически детерминированых (HD) кошельков этот процесс упростился. Детерминированный кошелек подразумевает создание всех его адресов из единой отправной точки –единой начальной фразы , которую принято обозначать как SEED фраза или просто SEED. webtricks отмечает, что на сегодняшний день детерминированные адреса создаются в более чем 95% некастодиальных кошельков, подчеркивая при этом, что если в некоторых кошельках это не так, то такими кошельками пользоваться не стоит. Весь процесс получения биткойн адресов сопровождается многочисленными примерами авторского кода, написанного на Javascript. Такой подход позволяет протестировать этот процесс на персональном компьютере без необходимости загрузки или развертывания какой-либо сторонней утилиты. 9 частей, на которые разбито содержание статьи: 1. Генерация случайной последовательности или энтропии. (#post_one) 2. Получение контрольной суммы и сборка выходной последовательности (выходного вектора). (#post_two) 3. Преобразование выходного вектора в мнемонические коды. (#post_three) 4. PBKDF2 или функция удлинения ключа. (#post_four) 5. Приватный/секретный Мастер-Ключ, Публичный/открытый Мастер-ключ и Кодирующая Цепочка (Chain Code). (#post_five) 6. Путь деривации/порождения (Derivation Path) и BIP-44. (#post_six) 7. Порождение Дочернего Приватного Ключа (Child Private Key Derivation). (#post_seven) 8. Создание биткойн-адресов из приватных ключей. (#post_eight) 9. JavaScript коды. (#post_nine) 1. Генерация случайной последовательности или энтропии. Автор начинает эту часть с того, что первые слова, сказанные им в самом начале статьи, о том, что отправной точкой иерархического кошелька служит начальная фраза, или как говорят мнемоника, не совсем правдивы. Чтобы получить мнемонику, сначала нужно сгенерировать энтропию. Защита кошелька, должна быть основана на чем-то непредсказуемом, поэтому используется энтропия в 128-256 бит. Самый простой способ получить энтропию - это подбросить монетку. Нужно взять монету и подбросить ее 128 раз, а затем записать ноль, если она ляжет решкой, и единицу, если выпадет орел. После 128 подбрасываний получится случайная последовательность нулей и единиц c требуемой энтропией, которая есть не что иное, как мера “случайности”. Чтобы повысить безопасность своего кошелька, тоже самое можно проделать и 256 раз, (чем больше энтропия, тем выше безопасность). Чтобы лучше понять этот процесс, можно посмотреть на нижерасположенную картинку: https://i.imgur.com/4T4lIbP.png Далее автор отмечает, что полученная последовательность нулей и единиц является четко выраженной отправной точкой, но она должна быть сгенерирована как можно более случайным образом. Если используется слабый генератор случайных чисел, хакеры могут легко взломать такую последовательность (имеется в виду догадаться о ней) и украсть средства. 2. Получение контрольной суммы и сборка выходной последовательности (выходного вектора). Автор указывает, что получив 128-битную энтропию, нужно сгенерировать для нее контрольную сумму. Контрольная сумма - это не что иное как сигнатура, прикрепляемая к объектудля того, чтобы убедиться, что пользователь не ошибся при его копировании. Чтобы найти сигнатуру полученной энтропии, нужно, согласно BIP-39, получить ее хэш используя функцию хеширования SHA-256. Но прежде всего необходимо преобразовать запись для рассматриваемой энтропии, а именно из двоичной (Base2) перейти в шестнадцатеричную ( Base16) систему исчисления. Base2 означает, что для выражения числа используется 2 символа, «0» и «1». В свою очередь Base16 для выражения числа использует 16 символов: 0,1,2,3,4,5,6,7,8,9, a, b, c, d, e, f. е Рисунок внизу показывает, как выполняется такое преобразование: https://i.imgur.com/I2HzUOk.png Можно увидеть, что 0001 в Base2 (в двоичной системе) представлено в шестнадцатеричной системе счисления символом 1, 0010 представлено символом 2 и так далее. Итак, энтропия в шестнадцатеричном формате представляется как 91d3785bf884c639f600b3e587083265. Важный момент здесь тот, что обе записи представляют одно и то же, но системы исчисления для них отличаются. Далее автор возвращается непосредственно к вопросу контрольной суммы для обсуждаемой энтропии и приводит результат ее (энтропии) хеширования функцией SHA-256: SHA-256 hash от 0x91d3785bf884c639f600b3e587083265 = effdb98e4c4ac27c670f704c39a2e0ba8b85bc4561a7a02a6297e465ed155d30 Хэш - это 256-битное число, представленное 64-мя шестнадцатеричными символами. Другими словами, каждый шестнадцатеричный символ представляет 4 бита. Согласно BIP-39, вместо использования всего хеша, только первые (величина энтропии / 32) бита хеша используются в качестве контрольной суммы. Величина энтропии здесь равна 128, что при делении на 32 дает 4. Итак, в качестве контрольной суммы берутся только первые четыре бита хэша. Если величина энтропии была бы равна 256, то в качестве контрольной суммы брались бы 256/32 или первые 8 бит хеша. Как уже говорилось, каждый шестнадцатеричный символ представлен четырьмя битами, первые четыре бита рассматриваемого хэша в шестнадцатеричном формате представлены символом «e». Поэтому контрольная сумма хэша - это «e» в шестнадцатеричном формате и 1110 в двоичном. Добавление этой контрольной суммы в конец последовательности создаст выходную последовательность, выраженную в шестнадцатеричной системе, как 0x91d3785bf884c639f600b3e587083265e, или в Base2 как: https://i.imgur.com/rgP7r2F.png 3. Преобразование выходного вектора в мнемонические коды. webtricks напоминает, что полученный размер выходного вектора составляет 132 бита, и Следующий шаг который необходимо предпринять, это его разбиение на отдельные кусочки размером в 11 бит. 132 поделенное на 11 дает 12, поэтому получается 12 фрагментов. (Если использовать 256-битную энтропию, получится 24 фрагмента.) Вот эти 12 фрагментов: 10010001110 10011011110 00010110111 11110001000 01001100011 00011100111 11011000000 00010110011 11100101100 00111000010 00001100100 11001011110 каждый из них - это двоичное число. Наименьшее значение, которое может быть представлено фрагментом это 00000000000, или 0 в десятичной системе, к то время как максимальное значение это 11111111111, или 2047 в десятичной системе. Таким образом, каждый фрагмент может принимать значение от 0 до 2047. BIP-39 определяет 2048 слов, отображаемых числами от 0 до 2047. Числовые отображения этих слов представлены в таблице BIP-39 WORDS (https://webtricks.website/words), размещенной автором на странице его персонального сайта. Из таблицы можно увидеть, что десятичные значения наших блоков: 1166, 1246, 183, 1928, 611, 231, 1728, 179, 1836, 450, 100, 1630.Выбирая соответствующие им слова, можно получить следующий мнемонический код: Code: mushroom orange black valve erase brother submit biology tortoise debate arrive slim 4. PBKDF2 или функция удлинения/растяжения ключа PBKDF2 (основанная на пароле функция формирования ключа./ Password-based Key Derivation Function) используется как мера защиты . Для повышения защищенности мнемонического кода в этой функции может использоваться «парольная фраза». Много полезного о PBKDF2 можно почерпнуть из Википедии (https://en.wikipedia.org/wiki/PBKDF2). Автор ясно дает понять, что, в процессе создания адресов биткойна, функция PBKDF2 применяется для удлинения мнемонического кода, при этом используются 2048 итераций алгоритма HMAC-SHA512. Алгоритм принимает два параметра: один из них это мнемонический код, второй – модификатор входа хеш-функции или кратко соль (salt). Если пользователь отказывается от использования пароля , то в качестве соли выступает строка со значением 'mnemonic'. Но, если в качестве пароля пользователь решит использовать скажем слово «webby», то соль превратится в 'mnemonicwebby', парольная фраза подцепляется к концу строчки 'mnemonic'. Следовательно, функция PBKDF2 примет следующий вид: Code: DK = PBKDF2(PRF, Password, Salt, c, dkLen) где PRF - псевдослучайная функция (здесь HMAC) Password - это мнемонический код Соль - это строка 'mnemonic' c – число итераций, 2048 для PBKDF2 dkLen - желаемая длина ( в байтах) производимого ключа (поскольку на выходе необходимо получить SEED размером в 512-бит, параметру dkLen предписано значение в 64 байта, 1 байт = 8 бит). DK относится к результирующему ключу или SEED размером в 512-бит. Для использованных параметров он равен: Code: 65729d81d461591bac7384dea43dbd44438053cd1fdc113e0769c49c5fde025ba331eed2077497634e619948437d0448e769a86c0cbbecf01b13fd53540743b3 5. Приватный/Секретный Мастер-Ключ, Публичный/Открытый Мастер-ключ и Кодирующая Цепочка (Chain Code). Автор еще раз напоминает, что основной целью использования SEED является получение иерархической древовидной структуры, в которой каждый приватный (секретный, закрытый) или публичный (открытый) ключ порождается своим родителем, и который в свою очередь порождает дочерние элементы (ключи). На вершине иерархии находится Master Private Key. Это секретный ключ первого уровня, у которого нет родителя. Для нахождения этого ключа и Chain Code используется криптографическая функция HMAC-SHA512, которая в качестве одного из двух своих параметров использует 512-битный SEED, полученный в разделе 4. Вторым ее параметром служит фиксированная строка, а именно 'Bitcoin seed'. HMAC(SEED, 'Bitcoin seed') = Hash Результирующий хеш, размером в 512-бит, принимает вид: Code: a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a5bc9d1368631ae579f02ed8e46a56dd9dd9de8ac59e3c4e18247ff96988bdf1f Далее webtricks обращает внимание на то, что размер получаемой таким образом выходной последовательности составляет 512 бит или 128 шестнадцатеричных символов. Первые 256 бит (первые 64 шестнадцатеричныхсимвола) и служат секретным мастер ключом (Master Private Key), в то время как следующие за ними 256 бит используется как кодирующая цепочка (Chain Code). Отсюда, Code: Master Private Key: a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a Используя криптографию на эллиптических кривых (Elliptic Curve Cryptography) можно из секретного мастер ключа получить открытый мастер ключ (Master Public Key). webtricks отсылает читателя к созданной им теме (https://bitcointalk.org/index.php?topic=5223167) по ECC, чтобы проследить как открытый ключ получается из секретного ключа. Тот же самый процесс справедлив для открытого мастер ключа. Code: Наш Master Public Key: 03d1cc1f6bdea4d17eb7f2573d676f9ddb087f8b784c912c4466407781d8acfe38 6. Путь деривации/порождения (Derivation Path) и BIP-44. webtricks проводит аналогию пути деривации и обычной карты, указывающей путь, который ведет к искомой точке через множество дорог, а в данном случае через дочерние элементы, получаемого из секретного мастер ключа, к адресу биткойна. Согласно BIP-44 этот путь для основной сети Bitcoin можно определить следующим образом: Code: Path format: m / purpose' / coin_type' / account' / change / address_index Наглядное представление об этом пути можно получить из нижеследующей картинки :
Title: Re: webtricks: SEED и получение адресов биткойна Post by: XEOP$ on February 22, 2021, 04:51:04 PM Продолжение.
Из приведенного автором рисунка следует, что секретный мастер ключ указывает на 45-го усиленного потомка, в свою очередь 45-й потомок на его первого усиленного потомка и так далее и наконец каждый из потомков первого стандартного потомка будут служить в качестве секретных ключей для искомых биткойн адресов. Далее автор объясняет разницу между усиленными и стандартными потомками. Когда говорится о «первом усиленном потомке», на самом деле подразумевается (231 + 1) -й потомок. Для облегчения понимания 231 заменяют символом штриха ('). Итак, 231 + 1 или 2147483649-й дочерний элемент родителя является первым усиленным (или 0 ' в штрих обозначениях) дочерним элементом. Для дальнейшего обсуждения пути деривации автор отсылает к теме одного из пользователей (blue Snow) форума : https://bitcointalk.org/index.php?topic=5243350 7. Порождение Дочернего Приватного Ключа (Child Private Key Derivation) Продолжая, автор переходит к рассмотрению получения дочернего ключа, для чего используется алгоритм хеширования HMAC-SHA512. Как уже говорилось криптографическая функция HMAC-SHA512 требует для себя 2 параметра – один из них это сообщение (Message) и второй – это секретный ключ. В данном случае роль сообщения берут на себя или секретный или открытый мастер ключи, сцепленные (конкатенированные) с дочерним индексом (Index), а роль секретного ключа принимает на себя кодирующая цепочка (Chain Code). Отсюда, Hash = HMAC(master key + index, chain code) Отмечается, что в случае получения усиленного потомка в качестве сообщения используется секретный мастер ключ, в то время как при для получения стандартного (normal) потомка используется открытый мастер ключ. Весь процесс выглядит следующим образом : УРОВЕНЬ 1: Получение 45-го усиленного потомка мастер ключа ( а поскольку он усилен используется закрытый мастер ключ) Code: Master Private Key = a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a (взято из раздела 5) webtricks обращает внимание на то, размер выходной последовательности HMAC(message, key) составляет 512 бит из которых левые 256 бит используются для создания секретного ключа 45-го усиленного потомка (дочернего элемента) , а правые 256 бит представят кодовую цепочку (Сode Chain) этого потомка. Итак, для создания секретного ключа 45-го усиленного потомка (Private Key of 45th Hardened Child of Master Private Key) левые 256 бит, рассматриваемые в 16-ричном представлении прибавляются к родительскому (в данном случае мастер) секретному ключу (Parent Private Key ), а именно производится операция сложения по модулю 'n', определяемому стандартом SECG Vol 2 (https://www.secg.org/sec2-v2.pdf) Code: Left 256 bits = 7fc9ce32a6aeffbeaf5057f266f0d6ed6383ed84f21c96d53c0c1e3838a87e24 УРОВЕНЬ 2: получение первого усиленного потомка от потомка уровня 1 (поскольку он усилен, используется закрытый ключ) Code: Private Key = 2096bf7f3a4ea9c667e7255219f77a6e5ccedba2546abbcfc9468a4925f5221d УРОВЕНЬ 3: получение первого усиленного потомка от потомка уровня 2 (поскольку он усилен, используется закрытый ключ) Code:
УРОВЕНЬ 4: получение первого стандартного потомка от потомка уровня 3 (поскольку он стандартный, используется открытый ключ) Code: Private Key = 27b52d3d12ea694ced4d4ee5261d69fa06cfba73d318e734b586ef8d7738b9ee Code: Private Key = e519213b4099dc0a4f26d22ca0a09add7ebc7c6e3964d57f46617f8db522a97a 8. Создание биткойн-адресов из приватных ключей Переходя к рассмотрению процесса получения биткойн-адресов, webtricks обращается к 3-м секретным ключам (с индексами 00000000, 00000001 и 00000002) уровня 5. Он говорит, что если нужно получить больше ключей, то все что для этого необходимо это продолжать увеличивать индекс на 1. В частности , 00000003 это индекс для следующего секретного ключа, ну и так далее. Также он напоминает, что индекс берется в шестнадцатеричном формате, поэтому после 00000009 следующим индексом будет 0000000a, а не 00000010. Тема webtricks , в которой он подробно объясняет, как генерируются из закрытого ключа Legacy адреса (адреса, начинающиеся с «1») можно найти по следующей ссылке How Bitcoin Addresses are generated? Understand the Math behind Bitcoin (https://bitcointalk.org/index.php?topic=5223167.msg53772308#msg53772308) Если следовать рассуждениям указанной темы, то можно сгенерировать первые три (в иерархии) Legacy адреса биткойна, используя закрытые ключи из раздела 7. Этими адресами будут : Quote 1MbJqqvN8ZPYsUch45HdRAxKbH6bJeGfZi 1GMpMNYwhb7Wvu8q1Zy52MtZUGWvLgCXak 12fv5eg3kzBgZQy7ue2yYmC9xXohmKWGR3 В обсуждаемой же работе webtricks фокусируется на адресах P2SH. P2SH сильно отличается от адреса P2PKH (Legacy), который создается из хэша открытого ключа. В отличие от такого сценария, для P2SH адреса сначала создается скрипт, а затем вычисляется его хэш. Транзакция делается в направлении скрипта, который может быть буквально любым и при этом отправителю транзакции не обязательно знать, что означает сам сценарий (скрипт). Биткойн имеет свой собственный язык сценариев( SCRIPT), который определяет множество операций, таких как OP_ADD, OP_EQUAL и другие. Итак, можно без всякого преувеличения создать любой сценарий, например такой, «что нужно добавить к 3 чтобы получить 5», получить хэш этого скрипта и использовать этот хеш в качестве адреса P2SH. Перечисления, полученные на этот адрес P2SH, можно потратить путем предоставления исходного скрипта ( т.е. «что нужно добавить к 3 чтобы получить 5») и скрипта, который предоставляет его решение, т.е. «2» вместе с хешем. P2SH можно использовать для создания гораздо более сложных сценариев, но одним из наиболее распространенных типов P2SH является P2WPKH-in-P2SH, который означает использование P2PKH внутри скрипта P2SH. Этому типу соответствуют адреса, начинающееся с цифры «3». Далее автор переходит непосредственно к созданию таких адресов: Схема для формата P2WPKH-in-P2SH определена в BIP-49. Как уже говорилось для создания иерархически детерминированных Legacy адресов используется 45-й усиленный потомок секретного мастер ключа ( Master Private Key). Однако для P2WPKH-in-P2SH используется 50-й усиленный потомок, поэтому путь деривации превращается в следующий: Code: m / 49' / 0' / 0' / 0 / address_index За исключением этого, все остальное подобно тому , как обсуждалось разделах 6 и 7, поэтому webtrics повторяет процедуру с секретным мастер ключом, то есть a0ccf14c939faa07b896cd5fb306a37fb3f9cb041196c5364d0cca9dbd82e53a, описанную им в разделе 7 и получает три секретных ключа, которые служат ему в качестве первых 3-х стандартных потомков в пути деривации m / 0 '/ 0' / 0 (т.е. потомков уровня 5): Code: Private Key of first normal child of Level 4 Child = 26e1061459e7961eeac018efa765339d785bd30de91f8fade64c639b275d74c4 (to be used for deriving first bitcoin address) Далее, используя ECC, он получает следующие открытые ключи (напоминания при этом , что для того, чтобы узнать как из секретного ключа получается открытый ключ можно обратиться к созданной им для этого cпециальной теме (https://bitcointalk.org/index.php?topic=5223167.msg53772308#msg53772308): Code: Public Key of first normal child of Level 4 Child = 021549dd72d89cbc844bb74ab6247239cf60d184cbfb0cfc4d024150a4985412fe (to be used for deriving first bitcoin address) Прежде чем перейти к объяснению происходящего webtrics предлагает ознакомиться с нижеследующим рисунком, который схематично описывает весь процесс преобразования открытого ключа в биткойн-адрес: Шаг №1: с помощью функции SHA-256 происходит хеширование открытого ключа: Code: SHA-256(public key) = Hash Шаг №2: полученный хеш хешируется функцей ripemd160 Code: RIPEMD160(hash) = Hash160 Шаг №3: к началу Hash160 прицепляется 0х0014 Code: serialization = 0x0014 + Hash160 Примечание: 0x00 представляет OP_0, а 0x14 - это размер данных (в шестнадцатеричном формате) , помещаемых в стек. Отсюда, скрипт P2WPKH-P2SH это OP_0 PushData <hash>. Шаги №4 и №5: Вычисляются хеши скрипта: Code: SHA-256(script) = Hash Шаг №6: к началу Hash160 прицепляется байт кодировки в виде 0x05 : Code: serialization = 0x05 + Hash160 Шаг №7: Вычисление контрольной суммы через двойное хеширование: Code: checksum = first four bytes of SHA-256(SHA-256(hash)) Code: final serialization = 052d7193893e4143fc11bb69c7f004452198bdf6cddcd3b30c Отсюда 35qJPbZX23wt3uuB9nz4pxhoouUfG28zxB - это первый адрес в иерархии биткойн адресов. Title: Re: webtricks: SEED и получение адресов биткойна Post by: XEOP$ on February 22, 2021, 04:51:16 PM Продолжение.
ПРИМЕЧАНИЕ к этой части, сделанное webtrics. Для предотвращения раздувания темы в эту часть не включены расширенные ключи (Extended Keys). Они являются неотъемлемой частью кошельков HD (HD - иерархически детерминированных) и помогают в иерархическом импорте адресов без необходимости использования мнемонического кода. Таким ключам будет посвящена отдельная тема. 9. JavaScript коды Действующий код: https://webtricks.website/seed (https://webtricks.website/seed) Ссылка GitHub: https://github.com/web-tricks/seed-guide (https://github.com/web-tricks/seed-guide) Примечания webtrics к кодам: Коды включают в себя комментарии, но в случае затруднений можно ему задавать вопросы прямо в теме. Коды не прошли повторную проверку или тестирование, поэтому не рекомендуется их использование в любом виде в разрабатываемых продуктах. При нахождении возможных ошибок автор просит дать ему знать об этом в его теме. При написании кодов использована библиотека CryptoJS для алгоритмов SHA-256, RIPEMD-160 и HMAC-SHA512. Файлы кодов. File 1: mnemonic.js ( https://github.com/web-tricks/seed-guide/blob/main/mnemonic.js) Code: //Generating random 128 bits. 128 - 256 bits can be used but for this tutorial we are strictly generating 128 bits entropy File 2: p2pkh.js (https://github.com/web-tricks/seed-guide/blob/main/p2pkh.js) Code: //This function will generate Legacy bitcoin address (public key hash) using public key File 3: p2sh.js (https://github.com/web-tricks/seed-guide/blob/main/p2sh.js) Code: //This function will generate P2SH bitcoin address (P2WPKH-in-P2SH) using public key File 4: ecc.js (https://github.com/web-tricks/seed-guide/blob/main/ecc.js) Code: //This file contains code for generating public key from private key using Elliptic Curve Cryptography File 5: bs58.js (https://github.com/web-tricks/seed-guide/blob/main/bs58.js) Code: //This javascript code for base58 encoding is taken from https://gist.github.com/diafygi/90a3e80ca1c2793220e5/ File 6: address.js (Link: https://github.com/web-tricks/seed-guide/blob/main/address.js) Code: //This function will take mnemonic code as the input and produce addresses File 7: words.js Файл можно загрузить отсюда: https://github.com/web-tricks/seed-guide/blob/main/words.js File 8: index.html ( https://github.com/web-tricks/seed-guide/blob/main/index.html) Code: <!DOCTYPE html> File 9: bech32.js (https://github.com/web-tricks/seed-guide/blob/main/bech32.js) Code: //This function will generate P2SH bitcoin address (P2WPKH-in-P2SH) using public key Чтобы запустить код необходимо сохранить все файлы в одной папке и открыть в браузере файл index.js Title: Re: webtricks: SEED и получение адресов биткойна Post by: XEOP$ on February 22, 2021, 05:20:36 PM reserved
|