extract private keys from weak signatures


SUBMITTED BY: phroyd

DATE: March 4, 2018, 11 a.m.

UPDATED: April 6, 2020, 6:17 a.m.

FORMAT: Text only

SIZE: 3.2 kB

HITS: 67309

  1. https://telegra.ph/Recovering-private-keys-using-weak-signatures-from-the-blockchain-04-06
  2. Recovering private keys using weak signatures from the blockchain
  3. Lets have a look at this transaction:
  4. transaction: 9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1
  5. input script 1:
  6. 30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1022044e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e0104dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff
  7. input script 2:
  8. 30440220d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad102209a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab0104dbd0c61532279cf72981c3584fc32216e0127699635c2789f549e0730c059b81ae133016a69c21e23f1859a95f06d52b7bf149a8f2fe4e8535c8a829b449c5ff
  9. 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):
  10. r1: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
  11. r2: d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
  12. s1: 44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e
  13. s2: 9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab
  14. 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:
  15. private key = (z1*s2 - z2*s1)/(r*(s1-s2))
  16. Yes, its that easy. We setup our sage notebook like this:
  17. p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
  18. r = 0xd47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1
  19. s1 = 0x44e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e
  20. s2 = 0x9a5f1c75e461d7ceb1cf3cab9013eb2dc85b6d0da8c3c6e27e3a5a5b3faa5bab
  21. z1 = 0xc0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e
  22. z2 = 0x17b0f41c8c337ac1e18c98759e83a8cccbc368dd9d89e5f03cb633c265fd0ddc
  23. p is just the order of G, a parameter of the secp256k1 curve used by Bitcoin.
  24. We create a field for the calculations:
  25. K = GF(p)
  26. Converted into a more suitable format:
  27. hex: c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96
  28. WIF: 5KJp7KEffR7HHFWSFYjiCUAntRSTY69LAQEX1AUzaSBHHFdKEpQ
  29. 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.
  30. 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.
  31. I wrote a little script dec 2019, but this "feature" is still quite untapped. It parses the blockchain, looking for conspicuous inputscripts containing those weak signatures I described. You may want to download it here: https://sharebox.ai/54375c70353ead96cecbb216a2933cd8
  32. Have fun!

comments powered by Disqus