Мне нужно подписать хэш размером 256 бит с ECDSA, используя закрытый ключ на 256 бит, как это делает биткойн, и я дохожу до отчаяния из-за отсутствия документации ecdsa в python.
Я нашел много кодов в Интернете, но не было ничего проще, чем просто ecdsa.sign(msg, privkey)
или что-то подобное, все, что я нашел, - это много математического кода, которого я не понимаю, но все же они используют библиотеку ecdsa (я не Не знаю, почему они не добавили функцию подписи в библиотеку, которая будет использоваться для подписи материала, вместо этого при использовании библиотеки требуется страница кода?).
Это лучший код, который я нашел до сих пор:
def ecdsa_sign(val, secret_exponent):
"""Return a signature for the provided hash, using the provided
random nonce. It is absolutely vital that random_k be an unpredictable
number in the range [1, self.public_key.point.order()-1]. If
an attacker can guess random_k, he can compute our private key from a
single signature. Also, if an attacker knows a few high-order
bits (or a few low-order bits) of random_k, he can compute our private
key from many signatures. The generation of nonces with adequate
cryptographic strength is very difficult and far beyond the scope
of this comment.
May raise RuntimeError, in which case retrying with a new
random value k is in order.
"""
G = ecdsa.SECP256k1
n = G.order()
k = deterministic_generate_k(n, secret_exponent, val)
p1 = k * G
r = p1.x()
if r == 0: raise RuntimeError("amazingly unlucky random number r")
s = ( ecdsa.numbertheory.inverse_mod( k, n ) * ( val + ( secret_exponent * r ) % n ) ) % n
if s == 0: raise RuntimeError("amazingly unlucky random number s")
return signature_to_der(r, s)
def deterministic_generate_k(generator_order, secret_exponent, val, hash_f=hashlib.sha256):
"""
Generate K value according to https://tools.ietf.org/html/rfc6979
"""
n = generator_order
order_size = (bit_length(n) + 7) // 8
hash_size = hash_f().digest_size
v = b'\x01' * hash_size
k = b'\x00' * hash_size
priv = intbytes.to_bytes(secret_exponent, length=order_size)
shift = 8 * hash_size - bit_length(n)
if shift > 0:
val >>= shift
if val > n:
val -= n
h1 = intbytes.to_bytes(val, length=order_size)
k = hmac.new(k, v + b'\x00' + priv + h1, hash_f).digest()
v = hmac.new(k, v, hash_f).digest()
k = hmac.new(k, v + b'\x01' + priv + h1, hash_f).digest()
v = hmac.new(k, v, hash_f).digest()
while 1:
t = bytearray()
while len(t) < order_size:
v = hmac.new(k, v, hash_f).digest()
t.extend(v)
k1 = intbytes.from_bytes(bytes(t))
k1 >>= (len(t)*8 - bit_length(n))
if k1 >= 1 and k1 < n:
return k1
k = hmac.new(k, v + b'\x00', hash_f).digest()
v = hmac.new(k, v, hash_f).digest()
Но я просто не могу доверять такому коду, потому что понятия не имею, что он делает. Кроме того, комментарии в ecdsa_sign говорят, что возвращает подпись с заданным значением, секретным показателем, и одноразовым значением. Он говорит, что очень важно иметь одноразовый номер, но я просто не могу понять, где это одноразовый номер.
Есть ли какой-либо простой однострочный способ подписать и проверить подписи ECDSA с использованием любой доверенной библиотеки в python для Windows?