【发布时间】:2016-03-30 19:19:59
【问题描述】:
我需要使用 256 位的私钥使用 ECDSA 签署一个 256 位的哈希,就像比特币一样,由于 python 中缺少 ecdsa 的文档,我感到绝望。
我在互联网上找到了很多代码,但没有什么比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 中的 cmets 表示返回给定值、秘密指数、和随机数的签名。它说拥有一个 nonce 非常重要,但我就是不知道那个 nonce 在哪里。
是否有任何简单的单行方法可以在 windows 上使用 python 中的任何受信任库来签署和验证 ECDSA 签名?
【问题讨论】:
-
不能用openssl签名吗?
-
使用 openssl 而不是 ecdsa 的优点是什么?
-
我想 ecdsa 库使用 openssl 所以没有区别,你可以使用 openssl openssl.org/docs/manmaster/crypto/ecdsa.html guyrutenberg.com/2013/12/28/… 访问你需要的任何东西
-
我同意您不必为了使用 ECDSA 而编写像示例中的代码那样详细的代码。你见过这个 Python ECDSA 库吗? github.com/warner/python-ecdsa