ECDSA: (v, r, s), что такое v?

Детерминированное подписание Tx с помощью RFC6979 возвращает v, r, s, где rи s— два значения, используемые в стандартных подписях ECDSA. v = 27 + (y % 2), поэтому 27 + паритет r, как указывает pybitcointools .

Таким образом, для четного rмы получаем v = 27, для нечетного rмы получаем v = 28.

Насколько важно значение v(27 или 28)? Почему необходимо иметь vзначение? Кроме того, почему это 27?

Кажется, это своего рода байт версии, похожий на байт версии, используемый в адресах кодирования. Не уверен в значении 27/28.
Ваша ссылка на github не работает; Я бы исправил это, но, видимо, мне нужно изменить как минимум 6 символов, чтобы это было действительным изменением.
Исправлена ​​ссылка @DavidGrayson. Возможно, Питер Уилле может прокомментировать, так как я читал, что 27 было выбрано произвольно, потому что это было «на полпути» между используемыми вариантами байтов версии, хотя я не могу найти этот источник на всю жизнь.
Это правильно. В то время это был произвольный выбор числа, потому что нам нужен был байт для передачи информации о восстановлении открытого ключа. Постараюсь позже написать полный ответ.

Ответы (4)

Это не имеет ничего общего с RFC6979, но имеет отношение к подписи ECDSA и восстановлению открытого ключа.

(r, s) — это нормальный вывод подписи ECDSA, где r вычисляется как координата X точки R по модулю порядка кривой n.

В Биткойне для подписи сообщений мы используем трюк, называемый восстановлением открытого ключа. Дело в том, что если у вас есть полная точка R (а не только ее координата X) и s, и сообщение, вы можете вычислить, для какого открытого ключа эта подпись будет валидной. Это позволяет «проверить» сообщение с адресом без необходимости знать полный ключ (мы просто восстанавливаем открытый ключ подписи, а затем хэшируем восстановленный ключ и сравниваем его с адресом).

Однако это означает, что нам нужны полные координаты R. Может быть до 4 разных точек с заданной «координатой X по модулю n». (2, потому что каждая координата X имеет две возможные координаты Y, и 2, потому что r+n все еще может быть допустимой координатой X). Это число от 0 до 3 мы называем идентификатором восстановления или recid. Поэтому мы возвращаем дополнительный байт, который также функционирует как байт заголовка, используя 27+recid (для несжатых восстановленных открытых ключей) или 31+recid (для сжатых восстановленных открытых ключей).

Строго говоря, recid не нужен, так как мы можем просто перебрать все возможные пары координат и проверить, соответствует ли какая-либо из них сигнатуре. Recid просто ускоряет эту проверку.

В общем, если h является кофактором, максимальное количество различных точек с заданной «координатой X по модулю n» будет равно 2 (h + 1). В случае secp256k1, который имеет кофактор 1, мы получаем 2(1+1) = 4.

Можете ли вы дать ссылку на код, который это реализует? Я собираюсь начать изучать C++, используя такие функции, которые я понимаю
Код подписи находится в libsecp256k1, в котором также есть код подтверждения, но в настоящее время он не используется. Для проверки в Bitcoin Core есть код C (см. pubkey.cpp), который выполняет серию вызовов OpenSSL для выполнения основной части работы. Я не уверен, что чтение криптографического кода C — лучший способ изучить C++ :)
Это скорее способ изучения вещей, которые я уже довольно хорошо понимаю и которые меня интересуют. Таким образом я изучил Python, и конечная цель — также узнать основное программное обеспечение.
@PeterWuille There can be up to 4 different points with a given "X coordinate modulo n". (2 because each X coordinate has two possible Y coordinates, and 2 because r+n may still be a valid X coordinate).Я понимаю первое (2 значения y для каждого x из-за симметрии) ... Но как работает последнее? то есть r+n may still be a valid X coordinate??
Координаты X и Y представляют собой числа по модулю p, размер поля, который составляет около 2 ^ 256 - 2 ^ 32 для secp256k1. Однако значения r и s в подписи являются модулем n, групповым порядком, который составляет около 2 ^ 256 - 2 ^ 128. Когда Rx находится между n и p, r уменьшается до Rx-n. Таким образом, если у вас есть значение r ниже 2 ^ 128-2 ^ 32, ему могут соответствовать 2 допустимых значения Rx.
@PieterWuille - это специфично для secp2561k или это можно обобщить для всех сигнатур эллиптических кривых? Кроме того, как это связано с этим ответом на крипто SE - crypto.stackexchange.com/questions/18105/… ?
ECDSA всегда поддерживает открытый ключ, независимо от кривой. Для кривых с кофактором > 1 все немного сложнее. Этот связанный ответ объясняет процедуру.
Какой, пожалуйста, из 4 возможных выходов (27..30) соответствует какому из возможных результатов. Например: 0 = положительный Y и X1? где это задокументировано?
@Sentinel Вы можете получить полную информацию о методе восстановления здесь: secg.org/sec1-v2.pdf
27 = более низкий X, четный Y. 28 = более низкий X, нечетный Y. 29 = более высокий X, четный Y. 30 = более высокий X, нечетный Y. Обратите внимание, что 29 и 30 встречаются чрезвычайно редко и на практике встречаются только в специально сгенерированных примерах. Есть только два возможных значения X, если r находится между 1 и (p mod n), что имеет шанс примерно 0,00000000000000000000000000000000000000373 % случайно.
@Souza / Питер - Спасибо. Я уже успел найти ответ на этот вопрос - это заняло у меня целую вечность! Я действительно нашел этот ASN.1 в sec1-v2.pdf после огромного количества копаний. Когда я нашел его, я подумал, что наткнулся на золото. Проблема в том, что документация Ethereum (я реализую легкий клиент Ethereum) не включает подробную информацию о протоколе, а официальные реализации, как правило, полагаются на библиотеки, которые идут туда, где уже прошел Биткойн, поэтому такие детали, как параметр «v», потеряны/похоронены. в очень, очень неясном коде.
@Sentinel моя борьба такая же. Я работаю над протоколом Ethereum, и они почти ничего не говорят об этом. И вы правы, они оба используют libsecp256k1.
@ Соуза - согласен. Это борьба. Я пытаюсь связаться с фондом Ethereum, чтобы собрать доступную документацию по протоколу и получить финансирование для этого. Я собираю легкий клиент, используя реактивные расширения и .NET, где я рассматриваю все сообщения протокола как потоки, проходящие через адаптеры уровня стека, и пытаюсь изолировать протокол верхнего уровня от различий более низкого уровня (например, diskv4 против v5 и т. д.) . К тому времени, как я закончу, я смогу написать об этом книгу.

Я не думаю, что v , который вы описываете, является частью RFC6979, потому что я не могу найти его в этом документе. Этот v является частью ecdsa_raw_signнеобработанной функции знака в pybitcointools, которая вызывает deterministic_generate_k, что является реализацией RFC6979.

RFC6979 просто помогает вам сгенерировать детерминированное значение k для подписи. Это не поможет вам сгенерировать r и s . Для генерации r и s вы просто используете обычный алгоритм ECDSA; вам не нужно обращаться к RFC6979 после того, как вы использовали его для генерации k . RFC6979 генерирует k , который является входом для алгоритма подписи, который может генерировать r и s .

Верно, но vпоявляется ли в разных реализациях? Я полагаю, что Pybitcointools — не единственная реализация, которая его использует.
Единственная другая реализация, которую я видел, это libsecp256k1 , которая не возвращает номер av. Эта библиотека предоставляет функцию с именем secp256k1_nonce_function_rfc6979, единственным выходом которой является 32-байтовый буфер данных.
secp256k1_ecdsa_sign_compact (старый API) или secp256k1_pubkey_serialize_compact (новый API) возвращают идентификатор восстановления (значение v, но без постоянного термина 27). Смотрите мой ответ.
Да, это vсвязано с подписью, а не с RFC6979.
@DavidGrayson да, изменил название :)

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

Вот шпаргалка:

  • 27несжатый открытый ключ, y-четность 0, величина xниже кривого порядка
  • 28несжатый открытый ключ, y-четность 1, величина xниже кривого порядка
  • 29несжатый открытый ключ, y-четность 0, величина x больше кривого порядка
  • 30несжатый открытый ключ, y-четность 1, величина x больше кривого порядка
  • 31 сжатый открытый ключ, четность по оси Y 0, величина xниже кривого порядка
  • 32 сжатый открытый ключ, четность по оси Y 1, величина xниже кривого порядка
  • 33 сжатый открытый ключ, y-четность 0, величина x больше порядка кривой
  • 34 сжатый открытый ключ, y-четность 1, величина x больше порядка кривой

Для любого v >= 35, кто может иметь дело с подписями Ethereum в соответствии с EIP-155 :

v = recovery_id + CHAIN_ID * 2 + 35

vнеобходим для восстановления открытого ключа. В результате восстановления открытого ключа из подписи ECDSA может быть возвращено 0, 1 или 2 балла. Для того, чтобы строго указать, какая точка соответствует «оригинальному» открытому ключу, используется дополнительный байт