Правильный ли размер подписи python-ecdsa? - PullRequest
0 голосов
/ 12 мая 2018

В биткойн-вики я обнаружил, что биткойн использует алгоритм ECDSA с кривой Secp256k1.

Соответствующие ссылки:

В первой ссылке указано, что закрытый ключ должен быть 32 байта, открытый ключ - 64 байта, а сигнатура обычно составляет 71-73 байта.Он говорит, что подпись может быть меньше с небольшой вероятностью.

Однако, когда я запускаю следующий код python3

>>> from ecdsa import SigningKey, SECP256k1
>>> private_key = SigningKey.generate(curve=SECP256k1)
>>> public_key = private_key.get_verifying_key()
>>> signature = private_key.sign(b'message')
>>> print((len(private_key.to_string()), len(public_key.to_string()), len(signature)))

, я получаю (32, 64, 64) в качестве вывода.Я ожидаю получить что-то вроде (32, 64, 72).

Я полагаю, что происходит одно из следующих событий:

  • Я неправильно понимаю статью в вики.
  • Я использую python-ecdsa неправильно
  • биткойн вики неверен
  • python-ecdsa не реализован правильно

Первые два наиболее вероятныиз них.

Может кто-нибудь объяснить мне, почему я получаю несоответствие между тем, что я ожидаю, и тем, что я на самом деле получаю?

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Единственная проблема с python-ecdsa - это производительность, потому что она слишком медленная.

Лучшая библиотека: starkbank-ecdsa

Как ее установить:

pip install starkbank-ecdsa

Как это использовать:

# Generate Keys
privateKey = PrivateKey()
publicKey = privateKey.publicKey()

message = "My test message"

# Generate Signature
signature = Ecdsa.sign(message, privateKey)

# Verify if signature is valid
print Ecdsa.verify(message, signature, publicKey)

Полная ссылка: https://github.com/starkbank/ecdsa-python

0 голосов
/ 12 мая 2018

Подпись ECDSA состоит из двух чисел, r и s, которые являются числами в диапазоне [1..n-1], где n - порядок кривой. n - это (известное) число в диапазоне [2 ^ (k-1) .. 2 ^ k-1], где k - это размер ключа. Таким образом, размер r и s, как правило, одинаков и иногда несколько меньше размера ключа в байтах.

Теперь r и s можно кодировать несколькими способами, два из которых являются общими:

  1. r и s кодируются DER как два типа INTEGER со знаком ASN.1 в последовательности SEQENCE ASN.1.
  2. 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). Обратите внимание, что «строки» в коде ссылаются на строки октетов , также известные как байтовые массивы - не текстовые строки.

...