Вопрос о подписании и проверке подписей с помощью Solidity был задан в этих вопросах, оба из которых я пытался изучить:
Как я могу подписать часть данных закрытым ключом адреса Ethereum?
Как я могу проверить криптографическую подпись, созданную парой адресных ключей Ethereum
Тем не менее, есть еще части информации, которые я, кажется, отсутствует.
Прежде всего, я хотел бы начать с вопроса о подписании. В примере строка Schoolbus
подписана адресом 0xd1ade25ccd3d550a7eb532ac759cac7be09c2719
, а результирующая подпись — 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
.
Все идет нормально. Теперь, что я хотел бы сделать, это проверить с помощью ecrecover
, что подпись действительно верна для данного адреса и данных. Дело в том, что ecrecover
принимает четыре аргумента: ecrecover(h, v, r, s)
. Помимо h
того, что это хэш и {v, r, s}
каким-то образом включает в себя подпись, что именно обозначают v, r и s? И как мне получить все необходимые значения из одной строки 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
?
Что я знаю, так это то, что он ecrecover
возвращает адрес, а проверка подписи — это, по сути, вопрос сравнения полученного адреса с ожидаемым. Тем не менее, вся процедура кажется излишне сложной.
Помимо этого, мне также было интересно, как я могу создать подпись, подобную этой, 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
или набор с {h, v, r, s}
использованием только Solidity, без обхода RPC-JSON, как в случае с вопросом — при условии, что я знаю закрытый ключ?
v, r и s — это параметры, которые можно проанализировать из подписи. Вот хороший пример из библиотеки утилит ethereumjs:
var sig = secp256k1.sign(msgHash, privateKey)
var ret = {}
ret.r = sig.signature.slice(0, 32)
ret.s = sig.signature.slice(32, 64)
ret.v = sig.recovery + 27
Обратите внимание, как вы можете анализировать каждое значение из данной подписи.
Несмотря на то, что вы можете подписать два разных сообщения одним и тем же закрытым ключом, процесс подписи (внутренне) генерирует случайное значение одноразового номера (k), которое используется как часть вычисления и должно быть разным для каждой сгенерированной подписи.
r и s вместе со связанным открытым ключом помогают проверить подлинность подписи.
Примечание: я не криптограф. Это то, что я выкопал, пытаясь ответить на те же вопросы, что и у вас. Я бы посоветовал посмотреть некоторые онлайн-ресурсы по эллиптическим кривым.
Aside from this, I was also wondering how I could produce a signature, either like this 0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601 or a set of {h, v, r, s} using Solidity alone, without the RPC-JSON detour as is the case in the question – при условии, что я знаю закрытый ключ?
Проблема, с которой вы столкнетесь при создании подписи из Solidity, заключается в том, что вам придется раскрыть закрытый ключ. В качестве альтернативы вы можете сгенерировать подпись вне обычного процесса транзакции Ethereum, используя одну из множества библиотек эллиптических кривых, и отправить полученную подпись в контракт.
recovery
Боюсь, что сама строка подписи не содержит свойства. Кроме того, просто убедитесь: нужен ли хэш для ecrecover
sha256?ecrecover
, не сработает без передачи правильного значения.Что именно означают v, r и s?
r
является R.x
значением точки подписи R
.s
является доказательством подписи дляR.x
v
параметр восстановления, используемый для облегчения проверки подписи.v
не требуется, но часто включается. Но что v
?
Поскольку сигнатура включает только x
координату точки , на эллиптической кривой Secp256k1 R
есть 0, 1, 2, 3 или 4 совпадающих координаты. y
Эти четыре потенциальных кандидата закодированы в нечто, называемое recovery_id
.
Идентификатор восстановления может иметь значения в 0..3
зависимости от следующих условий:
R.y
четным и R.x
меньше, чем порядок кривой n
:recovery_id := 0
R.y
нечетным и R.x
меньше порядка кривой n
:recovery_id := 1
R.y
четным и R.x
больше , чем порядок кривой n
:recovery_id := 2
R.y
нечетным и R.x
больше , чем порядок кривой n
:recovery_id := 3
Теперь мы знаем, как добраться до идентификатора восстановления. v
просто v = recory_id + 27
для биткойнов. В дополнение к v
значениям 27..30
, которые отражают только идентификатор восстановления, существует также понятие восстановления сжатых открытых ключей с использованием того же идентификатора восстановления, но с v
расширением v = recovery_id + 31
.
Но мы не говорим о Биткойне, так что последнее, но не менее важное, вы хотите взглянуть на EIP-155 , потому что мы больше не используем + 27
часть, которую Биткойн использовал для предотвращения защиты от повторного воспроизведения:
v = chain_id * 2 + 35 + recovery_id
В Ethereum v
отражает цепочку для защиты от повторного воспроизведения и идентификатор для восстановления подписи.
И как мне получить все необходимые значения из одной строки
0x2ac19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
?
Это просто конкатенированная строка "#{v}#{r}#{s}"
с:
v = 0x2a
r = 0xc19db245478a06032e69cdbd2b54e648b78431d0a47bd1fbab18f79f820ba407
s = 0x466e37adbe9e84541cab97ab7d290f4a64a5825c876d22109f3bf813254e8601
Это v
42.
chain_id = (v - 35) / 2
Теперь мы можем убедиться, что число v
42 действительно только в цепочке с идентификатором 3 (Ropsten).
Что я знаю, так это то, что он
ecrecover
возвращает адрес, а проверка подписи — это, по сути, вопрос сравнения полученного адреса с ожидаемым. Тем не менее, вся процедура кажется излишне сложной.
Я знаю, что это не вопрос, но буквально так работает криптография на эллиптических кривых: это просто математические операции с различными точками на кривой.
Адрес — это просто красиво отформатированная версия открытого ключа; открытый ключ — это просто точка на эллиптической кривой Secp256k1.
Подпись — это еще один момент. И если вы используете магию открытого ключа и магию подписи, в конце этого сложного математического процесса у вас есть две точки (открытые ключи), и если они полностью совпадают, подпись можно считать проверенной .
Это ecrecover
возвращает address
просто для вашего удобства: вы можете напрямую сравнить, совпадает ли адрес подписи с адресом подписавшего — и это намного проще сделать в Solidity, чем иметь дело с несжатыми открытыми ключами.
Я надеюсь, что это проливает свет на этот вопрос.
Мистер Чико
арик
Мистер Чико
арик
Мистер Чико
арик
ecrecover
есть, да. Но у меня нет окружающей среды выполнения на JavaScript, которая могла бы подготовить строку подписи в отдельные компоненты, прежде чем подавать ее в контракт Solidity. Сам контракт должен иметь возможность обрабатывать необработанную строку подписи.арик
web3.toDecimal
иString.prototype.slice
. Я пробую все ответы в контракте по мере их поступления.Гарен Вартанян
ecrecover
делает. Он сравнивает переданный хэш с хеш-сообщением, расшифрованным из подписи, чтобы убедиться, что они совпадают, а затем возвращает адрес, если он истинен.