Мне нужно подписать хэш из 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 говорят, что возвращает подпись с учетом значения, секретного экспонента, и nonce. В нем говорится, что очень важно иметь nonce, но я просто не могу понять, где это nonce.
Есть ли простой, однострочный способ подписи и проверки подписи ECDSA с использованием любой доверенной библиотеки в python в окнах?