Potential ECDSA disasters: Repeated nonce

Private Key Integer d

Public Key Curve point Q = dG

Signature Generation

Message Hash: h

Per-Signature “nonce”: Integer k

Signature on h: (r, s) r = x(kG) s = k ^{-1} (h + dr) mod n

Potential pitfall #2

If k is ever reused to sign distinct messages h 1 , h 2 , it is revealed

k = (h 1 − h 2 )(s 1 − s 2 ) ^{-1} mod n

and thus the long-term private key d is revealed.

#!/bin/python3.8
r =0x0861cce1da15fc2dd79f1164c4f7b3e6c1526e7e8d85716578689ca9a5dc349d
s1=0x6cf26e2776f7c94cafcee05cc810471ddca16fa864d13d57bee1c06ce39a3188
s2=0x4ba75bdda43b3aab84b895cfd9ef13a477182657faaf286a7b0d25f0cb9a7de2
z1=0x01b125d18422cdfa7b153f5bcf5b01927cf59791d1d9810009c70cd37b14f4e6
z2=0x339ff7b1ced3a45c988b3e4e239ea745db3b2b3fda6208134691bd2e4a37d6e1
# This function is from
# https://github.com/tlsfuzzer/python-ecdsa/blob/master/src/ecdsa/numbertheory.py
def inverse_mod(a, m):
"""Inverse of a mod m."""
if a == 0: # pragma: no branch
return 0
return pow(a, -1, m)

# Magic: https://en.bitcoin.it/wiki/Secp256k1
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

for (i, j) in [(1,1),(1,-1),(-1,1),(-1,-1)]:
z = z1 - z2
s = s1*i + s2*j
r_inv = inverse_mod(r, p)
s_inv = inverse_mod(s, p)
k = (z * s_inv) % p
d = (r_inv * (s1 * k - z1)) % p
print(f"Private key: {hex(d)}, {hex(k)}")
Private key: 0xe773cf35fce567d0622203c28f67478a3361bae7e6eb4366b50e1d27eb1ed82e, 0xaf7c9dd92162167d6aad26238f206284c30183941986caad8c0eaf8f14d9da46

发表评论

您的电子邮箱地址不会被公开。