Подпись ECDSA состоит из двух чисел, r и s, которые являются числами в диапазоне [1..n-1], где n - порядок кривой. n - это (известное) число в диапазоне [2 ^ (k-1) .. 2 ^ k-1], где k - это размер ключа. Таким образом, размер r и s, как правило, одинаков и иногда несколько меньше размера ключа в байтах.
Теперь r и s можно кодировать несколькими способами, два из которых являются общими:
- r и s кодируются DER как два типа INTEGER со знаком ASN.1 в последовательности SEQENCE ASN.1.
- r и s кодируются как два целых числа без знака статического размера с тем же размером, что и размер ключа (или порядок) в октетах или байтах .
Таким образом, разница в размере только потому, что значения r и s кодируются по-разному. Конечно, вам необходимо знать тип кодировки, прежде чем вы сможете проверить подпись.
Поскольку r и s являются абсолютно одинаковыми независимыми от кодировки, преобразование между двумя версиями относительно просто (если вы можете назвать все, что требует генерации или анализа структур ASN.1 в кодировке DER, «простым»).
Тип 1 был стандартизирован в ANSI X9.62, а тип 2, часто называемый плоским кодированием, обычно используется на встроенных платформах или смарт-картах.
r и s просто очень вероятны того же размера, что и n / размер ключа, но в принципе они могут быть, например, число 3. Вероятность того, что происходит, ужасно мала. Однако вы должны , а не выполнять какие-либо тесты с размерами r и s. Если любой из них меньше, чем на 8 байт, вы можете почесать голову, потому что вероятность этого между 1/2 ^ 63 и 1/2 ^ 64, т. Е. крайне маловероятно.
Итак:
- Я неправильно понимаю статью в вики.
Нет, статья в вики предполагает стандартную кодировку ANSI X9.62.
- Я неправильно использую python-ecdsa
Нет, пакет python-ecdsa просто использует другую кодировку, и вы удивитесь.
Нет, биткойн-вики предполагал, что для их протокола выбрана конкретная кодировка.
- python-ecdsa не реализован правильно
Определенно нет; по крайней мере, в отношении размера подписи.
Теперь о деталях реализации; в документации указано следующее:
Существует также несколько способов представления подписи. Методы sk.sign()
и vk.verify()
по умолчанию представляют его в виде короткой строки для простоты и минимальных накладных расходов. Чтобы использовать другую схему, используйте аргументы sk.sign (sigencode =) и vk.verify (sigdecode =). В модуле "ecdsa.util" есть вспомогательные функции, которые могут быть полезны здесь.
Поэтому попробуйте использовать sigencode=sigencode_der
, чтобы получить формат, ожидаемый статьей вики. Источник util.py
содержит все преобразования, которые могут вам понадобиться. Он использует number_to_string
для создания чисел статического размера. Эта функция также известна как I2OSP или примитив строки от целого к октету в PKCS # 1 (RSA). Обратите внимание, что «строки» в коде ссылаются на строки октетов , также известные как байтовые массивы - не текстовые строки.