Кошельки

Кошельки


Кошельки — это контейнеры для приватных ключей, как правило, реализуются в виде структурированных файлов или простых баз данных. Еще один метод создания ключей называется детерменистическая генерация ключей. Здесь, каждый новый приватный ключ получается использованием односторонней хэш-функции от предыдущего закрытого ключа, связывая их в последовательности. До тех пор пока вы можете воссоздать эту последовательность, вам нужен только первый ключ (известный как зерно или мастер-ключ). В этом разделе мы рассмотрим различные методы генерации ключей и структур кошелька, построенных вокруг этого.


Биткоин-кошельки пользователей хранят пары ключей, а не монеты. Пользователи подписывают транзакции ключами, таким образом доказывая права владения выходами транзакций (их монетами). Монеты хранятся в блокчейне в виде транзакций-выходов (часто обозначаемых как vout или txout).

Недетерминированные (случайные) кошельки

В первых Биткоин-клиентах, кошельками являлись просто коллекции случайно сгенерированных приватных ключей. Этот тип кошелька называется недетерминированным кошельком Тип-0. Например, клиент Bitcoin Core прегенерирует 100 случайных приватных ключей при первном запуске, и генерирует новые по мере необходимости. Этот тип кошелька прозвали "Просто Куча Ключей", или ПКК ("Just a Bunch Of Keys," JBOK) неудобны для резервного копирования, импорта/экспорта, и им на замену приходят детерминированные кошельки. Недостатком случайных ключей является то, что если вы создадите их много, то придется хранить копии их всех, а значит часто делать резервные копии кошелька, иначе, в случае безвозвратной потери ключа, средства будут навсегда потеряны. Подобное неудобство влечет за собой переиспользование адресов, что уменьшает конфиденциальность, позволяя строить ассоциации между различными адресами и транзакциями. Хотя клиент Bitcoin Core включает в себя недетерминированный кошелек Типа-0, его использование не рекомендуется разработчиками Bitcoin Core. На рис. ниже показан недетерминированный кошелек с коллекцией случайных ключей.

Детерминированные (с зерном) кошельки

Детерминистические, или кошельки "с зерном" — это такие, в которых приватные ключи происходят от общего зерна через использование односторонней хэш-функции. Само по себе зерно — это случайное число, в сочетании с другими данными, такими как номер индекса или "кодом цепи" позволяет получить приватные ключи. В детерминированном кошельке, для восстановления всех ключей достаточно знать зерно, а следовательно, достаточно одного единственного резервного копирования во время его создания. Зерна также достаточно для экспорта или импорта кошелька, что позволяет легко мигрировать все ключи пользователя между различными реализациями кошелька.


Недетерминированный кошелек Типа-0: коллекция случайно сгенерированных ключей

Мнемонические кодовые слова

Мнемонические коды — это последовательности английских слов, которые представляют собой (кодируют) случайное число, которое используется в качестве зерна для детерминированного кошелька. Последовательности слов достаточно, чтобы заново создать зерно, и из него уже воссоздать бумажник и все производные ключи. Приложение кошелька, реализующее детерминированные кошельки с мнемоническим кодом покажет пользователю последовательность из от 12 до 24 слов при создании кошелька. Это последовательность слов является резервной копией кошелька и может быть использована для восстановления и повторного создания всех ключи в том же или любом другом совместимом приложении кошелька. Мнемонические кодовые слова читаются и транскрибируются легче по сравнению со случайной последовательностью чисел.

Мнемоник коды описаны в Предложении Улучшения Биткоин номер 39 , которое в настоящее время находится в статусе черновика. Обратите внимание, что BIP0039 является проектом предложения, а не стандартом. В частности, есть другой стандарт, с другим набором слов, используемых в кошельке Electrum, предшествовавшим BIP0039, BIP0039 используется кошельке Trezor и некоторых других, несовместимых с реализацией в Electrum.

В BIP0039 описано создание мнемонического кода и зерна в следующем виде:

  1. Создать случайную последовательность (энтропию) длиной от 128 до 256 бит.
  2. Создать контрольную сумму случайной последовательности, взяв первые несколько битов из ее SHA256 хэша.
  3. Добавить контрольную сумму в конец случайной последовательности.
  4. Разделить последовательность на части длиной в 11 бит, и использовать их в качестве индекса по словарю из 2048 предопределенных слов.
  5. Полусить от 12 до 24 слов, представляющих собой мнемонический код.

Мнемонический код представляет от 128 до 256 бит, которые используются для получения более длинного (512-битного) зерна за счет использования функции удлинения ключа PBKDF2. Полученное зерно используется для создания детерминистического кошелька и производных от него ключей.


Иерархические детерминированные кошельки (BIP0032/BIP0044)

Детерминистические кошельки были разработаны, чтобы можно было легко получить много ключей из одного «зерна». Наиболее продвинутая форма детерминистических кошельков является иерархический детерминистический кошелек или HD-кошелек, описанный в стандарте BIP0032. Иерархические детерминистические кошельки содержат ключи в виде древовидной структуры, так что из родительского ключа можно вывести последовательность производных ключей, от каждого из которых, в свою очередь, также получается последовательность производных ключей и так далее без ограничения глубины вложенности. Эта древовидная структура показана на рисунке.


Иерархическую детерминистический кошелек Тип-2: дерево ключей, генерируемых из единственного зерна

Если вы разрабатываете Биткоин-кошелек, его следует реализовать в виде HD-кошелька согласно стандартам BIP0032 и BIP0044.

HD-кошельки предлагают два основных преимущества по сравнению с недетерминированными. Во-первых, структура дерева может быть использована для дополнительной организации, например, когда конкретная ветвь ключей используется для получения входящих платежей, а другая ветвь используется для получения сдачи для исходящих платежей. Ветвления ключей также могут быть использованы в корпоративной среде для различных отделов, филиалов, конкретных функций, или категорий бухгалтерского учета.

Второе преимущество HD-кошельов в том, что их пользователи могут создавать последовательности открытых ключей, не имея доступа к соответствующим приватным ключам. Это позволяет использовать HD-кошельки на небезопасных серверах или в режиме только приема средств с выдачей нового публичного ключа для каждой новой транзакции. Публичные ключи не должны быть предварительно загружены или получены заранее и сервер не содержит приватные ключи, которые могут использоваться для траты средств.


Создание HD-кошелька при помощи зерна

HD-кошельки создаются из единственного корневого зерна, которое представляет собой 128-, 256-, или 512-битное случайное число. Все остальное в HD-кошельке детерминистически производно от этого корневого зерна, которое делает возможным воссоздать весь HD-кошелек из этого зерна в любом совместимом ПО. Это позволяет просто осуществлять создать резервное копирование, восстановление, экспорт, и импорт кошельков, содержащих тысячи или даже миллионы ключей. Корневое зерно наиболее часто задается в виде ​​мнемонической последовательности слов.

Процесс создания мастер-ключей и мастер-цепочки для HD-кошелька показан на рисунке.


Создание мастер-ключей и кода цепочки из корневого зерна


Корневое зерно пропускается через алгоритм HMAC-SHA512, и полученный хэш используется для создания главного приватного ключа (m) и главной цепочки кодов. Главный приватный ключ (m) используется для генерации соответствующего главного публичного ключа (M), используя обычный процесс умножения на эллиптических кривых m * G, описанный ранее в этой главе. Код цепи используется для введения энтропии в функцию, которая создает производные ключи из родительских ключей, как мы увидим в следующем разделе.

Производные дочерние приватные ключи

Для получения дочерних ключей из родительских, иерархические детерминистические кошельки используют функцию деривации дочерних ключей (ДДК).

Функции деривации дочерних ключей основаны на односторонней хеш-функции, комбинирующей:

  • Родительский приватный или публичныйключ (несжатый ECDSA ключ)
  • Зерно, называемое кодом цепочки (256 бит)
  • Порядковым номером (32 бита)

Код цепи используется для введения случайных данных в процесс, так чтобы индекс не был достаточным для получения других соседних дочерних ключей. Таким образом, знание дочернего ключа не позволяет найти его братьев и сестер, при условии, что код цепи не известен. Исходное зерно кода цепи (в корне дерева) получен случайно, в то время как последующие коды цепи получены из родительского кода цепи.

Эти три элемента объединены и хэшированы для генерации дочених ключей следующим образом.

Родительский публичный ключ, код цепи и порядковый номер объединяются и хэшируются алгоритмом HMAC-SHA512, получая на выходе 512-битный хэш. Полученную хеш разделяется на две половины. Правые 256 бит хэш-кода становятся дочерним кодом цепи. Левые 256 бит хэша и индексный номер добавляются к родительскому приватному ключу для получения дочернего приватного ключа. В [CKDpriv] это проиллюстрировано для получения 0-ого (первого по порядку) производного ключа.


Расширение родительского приватного ключа для получения дочернего приватного ключа

Изменение порядкового номера позволяет получить другие дочерние ключи в последовательности, например Дочерний Ключ 0, Дочерний Ключ 1, Дочерний Ключ 2, и т.д. Каждый родительский ключ может иметь 2 млрд производных ключей.

Повторяя процесс одним уровнем ниже по дереву, каждый дочерний ключ может, в свою очередь стать родительским для своих собственных дочерних ключей, в бесконечном ряду поколений.

Использование производных ключей

Дочерние приватные ключи неотличимы от недетерминированных (случайных) ключей. Поскольку функция порождения является односторонней функцией, дочерний ключ не может быть использован для нахождения родительского ключа. Дочерний ключ также не может быть использован для нахождения соседних с ним ключей. Если у вас есть nый потомок, вы не можете найти его братьев и сестер, таких, как потомок n–1 потомок n+1, или каких-либо других потомков из последовательности. Только родительский ключ и код цепи могут произвести все дочерние ключи. Без дочернего кода цепи дочерний ключ так же не может быть использован для получения внучатых ключей. Для создания новой ветки последовательности внучатых ключей потребуется как дочерний приватный ключ, так и дочерний код цепи.

Так для чего можно использовать дочерний приватный ключ сам по себе? Он может быть использован для получения публичного ключа и Биткоин-адреса, а также для подписывания транзакций от имени этого адреса.


Дочерний приватный ключ, соответствующий публичный ключ, а также Биткоин-адрес все неотличимы от ключей и адреса, созданных случайно. Тот факт, что они являются частью последовательности не заметен за пределами HD-кошелька, который их создал. После создания они "работают" как "обычные" ключи.

Расширенные ключи

Как мы видели ранее, функция деривации ключей может быть использована для создания дочерних ключей на любом уровне дерева с помощью трех компонент: ключа, кода цепи и порядкового номера. Комбинация ключа и кода цепит называется расширенным ключем. Термин "расширенный ключ" может также рассматриваться как "расширяемый ключ" в том смысле, что с его помощью можно получать производные дочерние ключи.

Расширенные ключи хранятся и выглядят просто как конкатенакция 256-битного ключа и 256-битного кода цепи в 512-битовую последовательность. Есть два типа расширенных ключей. Расширенный приватный ключ является комбинацией приватного ключа и кода цепи и может быть использован для получения дочерних приватных ключей (и соответствующие им публичные ключи). Расширенный публичный ключ — это публичный ключ и код цепи, которые могут быть использованы для получения дочерних публичных ключей.

Расширенный ключ можно представить в виде основания какой-либо ветки в древовидной структуре HD-кошелька. Обладая основанием можно получить остальную часть ветки. Расширенный приватный ключ может создать полную ветвь, в то время как расширенный публичный ключ может создать только ветку публичных ключей.


Расширенный ключ состоит из приватного или публичного ключа и кода цепи. Расширенный ключ может создавать потомков в собственной ветке на общем дереве. Поделившись расширенным ключом можно дать доступ к ветке целиком.

Расширенные ключи кодируюутся с помощью Base58Check, что позволяет легко обмениваться ими между различными BIP0032-совместимыми кошельками. Для кодирования расширенных ключей в Base58Check используется специальный номер версии, который после кодирования выглядит как префикс "xprv" или "xpub". Так как расширенный ключ имеет длину 512 или 513 бит, результат кодирования намного длиннее, чем те Base58Check-закодированные строки, которые мы уже видели ранее.

Вот пример расширенного приватного ключа, закодированного в Base58Check:

xprv9tyUQV64JT5qs3RSTJkXCWKMyUgoQp7F3hA1xzG6ZGu6u6Q9VMNjGr67Lctvy5P8oyaYAL9CAWrUE9i6GoNMKUga5biW6Hx4tws2six3b9c

Вот соответствующий расширенный публичный ключ, также закодированный в Base58Check:

xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KECeeMVKZBPLrtJunSDMstweyLXhRgPxdp14sk9tJPW9

Производные публичные ключи

Как упоминалось ранее, очень полезное свойство иерархических детерминированных кошельков состоит в том, что с их помощью можно получать дочерние публичные ключи без обладания приватными ключамт. Это дает нам два способа получения дочернего открытого ключа: либо из дочернего приватного ключа, либо непосредственно из родительского публичного ключа.

Расширенный публичный ключ может быть использован, поэтому, в качестве производного для всех _публичных_ ключей (и только публичных) в этой ветке структуры HD-кошелька.

Эта удобная возможность позволяет создавать очень безопасные среды, где сервер или приложение будет иметь доступ к публичному расширенному ключу и не иметь приватных ключей вообще. Таким образом можно производить бесконечное число публичных ключей и Биткоин-адресов, но нельзя потратить деньги, присланные на эти адреса. Между тем, на другом, более безопасном сервере, расширенный приватный ключ может использоваться для получения всех соответствующих приватных ключей, чтобы можно было подписывать транзакции и тратить деньги.

Одно из распространенных применений этого решения является установка расширенного публичного ключа на веб-сервере, обслуживающем приложение электронной коммерции. Веб-сервер может использовать функцию деривации публичного ключа для создания нового Биткоин-адреса для каждой транзакции. Веб-сервер не будет содержать никаких приватных ключей, которые будут уязвимы для кражи. Без HD-кошелька, единственный способ сделать то же самое это сгенерировать тысячи Биткоин-адресов на отдельном защищенном сервере и затем загрузить их на сервер электронной коммерции. Такой подход является громоздким и требует постоянного обслуживания, так как надо гарантировать, что на сервере электронной коммерции не "кончатся" ключи.

Еще одно распространенное применение этого решения — это холодные и аппаратные кошельки. При таком сценарии, расширенный приватный ключ может храниться на листе бумаги или в электронном устройстве (например таком, как Trezor), в то время как расширенный публичный ключ может быть онлайн. Пользователь может создавать адреса "для получения" по желанию, в то время как приватные ключи надежно хранятся в офлайне. Для траты средств, пользователь может использовать расширенный приватный ключ при помощи офлайнового Биткоин-клиента или подписать транзакции при помощи аппаратного устройства-кошелька (например, Trezor). На рисунке проиллюстрирован механизм расширения родительского публичного ключа для получения дочерних публичных ключей.


Расширение родительского публичного ключа для создания дочернего публичного ключа

Укрепленные производные дочерние ключи

Возможность получения ветки производных публичных ключей из расширенного публичного ключа очень полезна, однако в ней заложен потенциальный риск. Доступ к расширенному публичному ключу не дает доступа к дочерним приватным ключам. Тем не менее, так как расширенный публичный ключ содержит код цепи, если дочерний публичный ключ известен, или как-то утек, он может использоваться с кодом цепи для получения всех остальных дочерних приватных ключей. Единственный утекший приватный ключ, совместно с родительским кодом цепи, раскрывает все приватные ключи всех детей. Хуже того, дочерний приватный ключ вместе с родительским кодом цепи могут быть использованы для выведения родительского приватного ключа.

Чтобы противостоять этой опасности, в HD-кошельках используется альтернативная функция деривации, называемая укрепленная деривация, которая "ломает" отношение между родительским публичным ключом и и дочерним кодом цепи. Функция укрепленной деривации использует родительский приватный ключ для получения дочернего кода цепи, вместо родтельского публичного ключа. Это создает "брандмауэр" в последовательности родитель/потомок, с кодом цепи, который не может быть использован для компрометации родительского или родственного приватного ключа. Укрепленная функция деривации выглядит почти идентично обычной функции выведения дочернего приватного ключа, за исключением того, что родительский приватный ключ используется в качестве входя для хэш-функции, вместо родительского публичного ключа, как показано на схеме.


Вывод дочернего ключа; исключает родительский открытый ключ

Когда используется укрепленная функция деривации приватных ключей, результирующий дочерний приватный ключ и код цепи полностью отличается от того, который получается в результате выполнения обычной функции деривации. Результирующая "ветка" ключей может быть использована для получения расширенных публичных ключей, которые не были бы уязвимы, так как они содержат код цепи, который не может использоваться для выявления каких-либо приватных ключей. Укрепленная деривация, следовательно, используется для создания "разрыва" в дереве выше уровня, где используются расширенные публичные ключи.

Простыми словами, если вы хотите использовать удобство расширенного публичного ключа по деривации ветви публичных ключей, не подвергая себя риску утечки кода цепи, вы должны произвести его от укрепленного прородителя, а не от обычного. Лучше всего, если потомки -1-го уровня всегда получены в результате укрепленной деривации, чтобы предотвратить компрометацию мастер-ключа.

Порядковый номер для обычной и укрепленной деривации

Порядковый номер, используемый в функции деривации — это 32-разрядное целое число. Чтобы легко отличать ключи, полученные с помощью обычной функции деривации ключей от ключей, полученных при помощи укрепленной функции, этот порядковый номер разделен на два диапазона. Порядковые номера между 0 и 231–1 (от 0x0 до 0x7FFFFFFF) используются только для нормальной деривации. Номера между 231 и 232–1 (от 0x80000000 до 0xFFFFFFFF) используются только для укрепленной деривации. Таким образом, если порядковый номер меньше 231, это означает, что дочерний ключ обычный, в то время как, если номер равен или больше 231, дочерний ключ укрепленный.

Для того, чтобы порядковый номер легче читаться, для укрепленных дочерних ключей он начинается с нуля, но с символом апострофа. Поэтому первый обычный дочерний ключ отображается как 0, в то время как первый укрепленный дочерний ключ (индекс 0x80000000) отображается как 0'. Далее второй укрепленный ключ имел бы номер 0x80000001 и отображался бы как 1', и так далее. Когда вы видите порядковый номер HD-кошелька i, это означает 231+i.


Источник: http://bitcoinbook-builds.mkvd.net

Report Page