You are on page 1of 2

i've found this today: http://telegra.

ph/Recovering-Bitcoin-private-keys-using-
weak-signatures-from-the-blockchain-02-27

Recovering private keys using weak signatures from the blockchain

Have a look at this transaction:

transaction: 9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1

input script 1:

30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1022044e1ff2
dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e0104dbd0c61532279cf72981c3
584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f
2fe4e8535c8a829b449c5ff

input script 2:

30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad102209a5f1c7
5e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab0104dbd0c61532279cf72981c3
584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f
2fe4e8535c8a829b449c5ff

This transactions contains two inputs and one output. You will notice there are
equal bytes at the start and at the end. The bytes at the end is the hex-encoded
public key of the address spending the coins - nothing wrong with that. But, the
first half of the script is the actual signature (r, s):

r1: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
r2: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1

s1: 44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e
s2: 9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab

You can see, r1 equals r2. This is quite a problem because now we are able to
recover the private key to this public key:

private key = (z1*s2 - z2*s1)/(r*(s1-s2))

Yes, its that easy. We setup our sage notebook like this:

p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
r = 0xd47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
s1 = 0x44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e
s2 = 0x9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab
z1 = 0xc0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e
z2 = 0x17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc

p is just the order of G, a parameter of the secp256k1 curve used by Bitcoin.


We create a field for the calculations:

K = GF(p)

Converted into a more suitable format:

hex: c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96
WIF: 5KJp7KEffR7HHFWSFYjiCUAntRSTY69LAQEX1AUzaSBHHFdKEpQ

Now we import it to your favourite Bitcoin wallet. It’ll calculate the correct
bitcoin address and we’ll be able to spend coins sent to this address.

The reason why this works? ECDSA requires a random number for each signature. If
this random number is ever used twice within the same private key it can be
recovered. This transaction was generated by a hardware bitcoin wallet using a
pseudo-random number generator that was returning the same “random” number every
time.

I wrote a simple script that parses the blockchain, looking for conspicuous
inputscripts containing those weak signatures I described. Download it here:
https://goo.gl/11YaCB

>>> Do not download this!


Paying 0.05 btc for this parser is way to much :)
Since he gave a nice description on this problem I was able to write this thing
from scratch, its quite simple.
And he is right, it works. You can download mine for a much cheaper price here:
http://bit.ly/2FA10W9

You might also like