I decided it was worthwhile to share this with everyone. Between hanging out on Reddit, I like to go back to the good old bitcointalk.org stomping grounds. I found this great little gem which is bound to get much attention from user ca333. Its a Small Python Script that checks any given Bitcoin address for weak transaction signing. The script is was small and executed with urllib2 for loading the data from blockchain.info. The only current caveat as it stands is that it will only check relatively fresh public keys (those with 50 transactions or less).
how does it work?
To be honest, ca333 really explains it well here with:
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.
If you are interested in more details on how the private key is calculated, please click the reference link above for further explanation.
DO NOT USE THIS TO HARM OTHERS!!!
USE THIS PROTECT YOURSELF AND YOUR APPLICATIONS!!!
I recommend using this tool if you are testing an online web wallet for the first time or if you are developing your own wallet system and want to test the integrity of the design. I spent about 40 minutes on the web trying out random different addresses and didn’t find any with a vulnerability to report which is definitely good. (give a round of virtual applause for the wallet devs making sure things are right!)
#!/usr/bin/python ################################################################################# # # #.______ _______. ______ ___ .__ __. # #| _ \ / | / | / \ | \ | | # #| |_) | ______ | (----`| ,----' / ^ \ | \| | # #| / |______| \ \ | | / /_\ \ | . ` | # #| |\ \----. .----) | | `----./ _____ \ | |\ | # #| _| `._____| |_______/ \______/__/ \__\ |__| \__| v0.1.2 # # # #GNU PL - 2015 - ca333 # # # #USE AT OWN RISK! # ################################################################################# import json import urllib2 import time import sys #for some reason blockchain.info api-chain is 59711 blocks short.. blockstart = 170399 blockstart += 59711 blockcount = urllib2.urlopen("https://blockchain.info/de/q/getblockcount").read() print "WELCOME TO R-scan v0.1.2!" print "ADDRESS-R-SCAN: " addr = raw_input("type address: ") urladdr = "https://blockchain.info/de/rawaddr/" + str(addr) #control api-url print urladdr addrdata = json.load(urllib2.urlopen(urladdr)) print "Data for pubkey: " + str(addr) print "number of txs: " + str(addrdata['n_tx']) #tx-details: y = 0 inputs = [] while y < addrdata['n_tx']: print "#################################################################################" print "TX nr :" + str(y+1) print "hash: " + str(addrdata['txs'][y]['hash']) print "number of inputs: " + str(addrdata['txs'][y]['vin_sz']) #only if #if addrdata['txs'][y]['vin_sz'] > 1: zy = 0 while zy < addrdata['txs'][y]['vin_sz']: print "Input-ScriptNR " + str(zy+1) + " :" + str(addrdata['txs'][y]['inputs'][zy]['script']) inputs.append(addrdata['txs'][y]['inputs'][zy]['script']) zy += 1 y += 1 print "compare: " xi = 0 zi = 1 lenx = len(inputs) alert = 0 #compare the sig values in each input script while xi < lenx-1: x = 0 while x < lenx-zi: if inputs[xi][10:74] == inputs[x+zi][10:74]: print "In Input NR: " + str(xi) + "[global increment] " + str(inputs[xi]) print('\a') print "Resued R-Value: " print inputs[x+zi][10:74] alert += 1 x += 1 zi += 1 xi += 1 #check duplicates #alert when everything ok if alert < 1: print "Good pubKey. No problems." sys.exit()
I ran the script and I have Reused R-Values, Now What?
Now you have two options:
Spend all your bitcoin right away and Don’t Care
Move your bitcoin to a different wallet entirely
Move your bitcoin to an offline generated paper wallet for storage and sweep key (when preparing to spend bitcoin that isnt stored on a wallet, use the private key – sweeping the key isn’t the same as importing it, its just using the key one time to transfer the bitcoin to a new wallet or sweeping it. If you import a private key, others who hold that private key could also by proxy control your bitcoin sent to this address – most modern wallets and major web wallets will send your spent bitcoin [ALL OF IT] and will return the change back to a remaining address) occasionally when funds are required to spend. Here is my abridged guide to paper wallets:
- save bitaddress.org as complete html
- turn off internet – unplug ur pc from it
- generate a random Bip password protected paper walllet (generate it 17 times then pick one of those randomly so you know its not just the 1st or 2nd one)
- print wallet
- save it someplace safe (DO NOT KEEP YOUR PASSWORD WITH THE PAPER WALLET)