Что такое сжатый биткойн-ключ?

Стандартный биткойн-клиент версии 0.6, по-видимому, использует сжатые ключи.

Кто они такие? Есть ли недостатки в их использовании? Любая несовместимость со старым программным обеспечением? Снижение криптографической стойкости?

Ответы (4)

Сжатый ключ — это просто способ хранения открытого ключа в меньшем количестве байтов (33 вместо 65). Нет никаких проблем с совместимостью или безопасностью, потому что это точно такие же ключи, просто хранящиеся по-другому. Первоначальное программное обеспечение Биткойн не использовало сжатые ключи только потому, что их использование было плохо задокументировано в OpenSSL. У них нет недостатков, кроме того, что требуется немного дополнительных вычислений, прежде чем их можно будет использовать для проверки подписи.

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

Итак, если старое программное обеспечение сталкивается со сжатым ключом (как это может произойти? в wallet.dat? в цепочке блоков? в широковещательной рассылке транзакции?), сможет ли оно его обработать?
Нет, не может. Но всегда запрещается пытаться прочитать wallet.datфайл с помощью более ранней версии программного обеспечения. Это разрешенный перерыв. (Вы все еще можете вручную извлечь дело, распаковать их и поместить в более раннюю форму, если вам нужно. Но такая совместимость не поддерживается. Вы не можете вернуться с более новым файлом кошелька, если не переведете данные. )
Чтобы ответить на ваш другой вопрос, только в формате wallet.dat. Сжатые ключи еще нигде не поддерживаются, потому что это было бы нарушением протокола.
Если это только для wallet.dat, зачем беспокоиться о нескольких байтах? Сохраненный 31 байт составляет мегабайт, только если у вас есть 33,825 ключей.
Старые клиенты могут проверять транзакции со сжатыми открытыми ключами, потому что Биткойн отправляет открытые ключи в OpenSSL без проверки их формата, а OpenSSL автоматически обрабатывает открытый ключ в соответствии с начальным байтом (0x04 для несжатого, 0x02/0x03 для сжатого).
Преимущество в основном для блокчейна и сети, поскольку теперь транзакции будут немного меньше. Кстати, это 33 байта вместо 65.
Итак, если я правильно понимаю, один закрытый ключ всегда связан с одним открытым ключом, представляемым в двух разных форматах, который связан с двумя адресами (от того, хешируется ли сжатая и несжатая форма ключа)? Таким образом, кто-то может отправлять монеты на любой адрес, но чтобы использовать эти монеты, мне нужно использовать правильную версию открытого ключа (который будет автоматически обрабатываться новым программным обеспечением, а старое — нет?)
У меня проблема с пониманием этого: у меня есть несжатый закрытый ключ, я ввожу его в bitaddress.org и получаю два общедоступных адреса: один сжатый и один несжатый. На одном у меня миллион долларов, на другом 0. И оба они исходят от одного закрытого ключа. Как это имеет смысл?
@Advanced Один закрытый ключ имеет один соответствующий открытый ключ. Но этот открытый ключ может быть представлен в двух формах: сжатой и несжатой. Каждая форма открытого ключа имеет соответствующий биткойн-адрес. Биткойны могут быть отправлены на адреса независимо от того, как этот адрес был сформирован.
@DavidSchwartz Ссылка на Secp256k1 в вашем посте не работает. Но: какое прекрасное объяснение того, как достигается это сжатие!
@Qqwy Спасибо. Я исправил ссылку, чтобы она указывала на что-то хоть немного актуальное.

Формат (закрытые ключи):

  • несжатый: 0x80 + [32-байтовый секрет] + [4 байта Hash() из предыдущих 33 байтов], кодировка base58
  • сжатый: 0x80 + [32-байтовый секрет] + 0x01 + [4 байта Hash() предыдущих 34 байтов], кодировка base58

Случай 1:

  • секрет (шестнадцатеричный): 11111111111111111111111111111111111111111111111111111111111111
  • несжатый:
    • секрет (base58): 5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh
    • открытый ключ (шестнадцатеричный): 044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1
    • адрес (база 58): 1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a
  • сжатый:
    • секрет (base58): KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp
    • открытый ключ (шестнадцатеричный): 034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
    • адрес (base58): 1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9

Получено из списка рассылки разработчиков биткойнов:

Этот ответ отличается от приведенного выше, где первый байт сжатого/несжатого (0x04 для несжатого, 0x02/0x03 для сжатого)
Похоже, что этот ответ относится к конкретному формату импорта/экспорта ключей биткойнов, а не к использованию самих сжатых ключей, а именно в OpenSSL. Я надеюсь, что это поможет будущим читателям сопоставить два ответа здесь.
Цитата вводит в заблуждение. Поскольку это цитата, ее, вероятно, не следует редактировать, но «4 байта хэша () предыдущих […] байтов» должны были быть «4 байта хэша (хеш ()) предыдущих […] байтов». Хеш-функция применяется дважды.
Хэш @Akater, примененный дважды, все еще остается хешем. Поскольку не сказано, какой функции Hash()соответствует, цитата верна. Я не знаю, какая функция используется, так что, может быть, напримерHash(x) = SHA256(SHA256(x))

Это может помочь разделить поля.

04
4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1

03 [может быть 02]
4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa
[отброшенное значение может быть вычислено из приведенного выше значения]

Более подробная информация опущена выше. 03 может быть 02, потому что отброшенное значение должно быть получено из сохраненного значения, и требуется один дополнительный бит информации. Это потому, что есть два корня [плюс и минус] при извлечении квадратного корня.

хорошее объяснение доступно в разделе Как я могу проверить, сжат биткойн-адрес или нет?

В частности, открытый ключ в биткойне представляет собой пару целых чисел (x, y). Для несжатых открытых ключей эти целые числа кодируются как 256-битные целые числа без знака с обратным порядком байтов, объединяются вместе, а затем добавляются к одному байту 0x04. Результат имеет длину 65 байт.

Для сжатых открытых ключей кодируется только координата x (как и выше, как 256-битное целое число без знака с обратным порядком байтов). Оказывается, координата y может принимать только одно из двух значений: одно четное и одно нечетное. Вместо одного байта 0x04 добавляется один байт 0x02 или 0x03 в зависимости от значения y (0x02 для четных, 0x03 для нечетных). Результат имеет длину 33 байта.

это 0x02 для y > 0 и 0x03 для y <0
@CiscoMmu, как узнать, y> 0 или <0?
На графике EC у вас есть 2 точки по координате y (+ve и -ve) для каждой точки по координате x.