Advertisement
Guest User

Bitcoin KeyChain: simple, single-file, Python key generator.

a guest
Aug 11th, 2014
3,292
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.77 KB | None | 0 0
  1. ####################################Python Bitcoin KeyChain
  2. #This program takes an initial private key (seed) and and increment (customincr), and generates a list of keys (wallet).
  3. #Then it saves a .txt file holding the list of related keys.
  4. #No need for custom libraries, the eliptic equations are built in!
  5. #For good security, roll lots of d10 dice to sequence a key somewhere between 2^50 and 2^253.
  6. #Then pick an increment, the larger the better, but keep it below 2^150.
  7. #This program WILL generate any address, the limits are suggestions, and invalid keys should close program.
  8. #Keep those two numbers safe, they can be used to recreate the entire wallet!
  9. #Also, this is a ready to use application, to enable prompt for seeds, scroll down and uncomment blocks noted.
  10. ##### Lawsky Aug, '14  , some of this code is from other sources, and is free for all purposes.
  11.  
  12. import hashlib, binascii # local imports required for conversions, they are standard with Python
  13. #import urllib2 #for blockchain query that is disabled
  14. #import json #for blockchain query that is disabled
  15.  
  16. Pcurve = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 -1 # The proven prime
  17. N=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 # Number of points in the field
  18. Acurve = 0; Bcurve = 7 # These two defines the elliptic curve. y^2 = x^3 + Acurve * x + Bcurve
  19. Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240  #x coordinate of GPoint
  20. Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424  #y coordinate of GPoint
  21. GPoint = (Gx,Gy) # This is our generator point. Trillions of dif ones possible
  22. t='123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' # Base58 Charset
  23.  
  24. def Byte2Hex(b): #Convert a byte string to hex number
  25.     out="";
  26.     for x in b:
  27.         y=hex(ord(x))[2:]
  28.         if len(y)==1:
  29.             y="0"+y
  30.         out+="%2s"%y    
  31.     return out
  32.  
  33. def Hex2Byte(hexStr): # convert hex number into a byte string
  34.     bytes = []
  35.     hexStr = ''.join( hexStr.split(" ") )
  36.     for i in range(0, len(hexStr), 2):
  37.         bytes.append( chr( int (hexStr[i:i+2], 16 ) ) )
  38.     return ''.join( bytes )
  39.  
  40. def Int2Byte(n,b):    #Convert a integer to a byte string of length b
  41.     out=""    
  42.     for i in range(b):
  43.         (n,m)=divmod(n,256)
  44.         out=chr(m)+out    
  45.     return out
  46.  
  47. def modinv(a,n=Pcurve): #Extended Euclidean Algorithm/'division' in elliptic curves
  48.     lm, hm = 1,0
  49.     low, high = a%n,n
  50.     while low > 1:
  51.         ratio = high/low
  52.         nm, new = hm-lm*ratio, high-low*ratio
  53.         lm, low, hm, high = nm, new, lm, low
  54.     return lm % n
  55.  
  56. def ECadd(a,b): # Not true addition, invented for EC. Could have been called anything.
  57.     LamAdd = ((b[1]-a[1]) * modinv(b[0]-a[0],Pcurve)) % Pcurve
  58.     x = (LamAdd*LamAdd-a[0]-b[0]) % Pcurve
  59.     y = (LamAdd*(a[0]-x)-a[1]) % Pcurve
  60.     return (x,y)
  61.  
  62. def ECdouble(a): # This is called point doubling, also invented for EC.
  63.     Lam = ((3*a[0]*a[0]+Acurve) * modinv((2*a[1]),Pcurve)) % Pcurve
  64.     x = (Lam*Lam-2*a[0]) % Pcurve
  65.     y = (Lam*(a[0]-x)-a[1]) % Pcurve
  66.     return (x,y)
  67.  
  68. def EccMultiply(GenPoint,ScalarHex): #Double & add. Not true multiplication
  69.     if ScalarHex == 0 or ScalarHex >= N: raise Exception("Invalid Scalar/Private Key")
  70.     ScalarBin = str(bin(ScalarHex))[2:]
  71.     Q=GenPoint
  72.     for i in range (1, len(ScalarBin)): # This is invented EC multiplication.
  73.         Q=ECdouble(Q); # print "DUB", Q[0]; print
  74.         if ScalarBin[i] == "1":
  75.             Q=ECadd(Q,GenPoint); # print "ADD", Q[0]; print
  76.     return (Q)
  77.  
  78. def numtowif(numpriv): #converts numerical private key to WIF
  79.  step1 = '80'+hex(numpriv)[2:].strip('L').zfill(64)
  80.  step2 = hashlib.sha256(binascii.unhexlify(step1)).hexdigest()
  81.  step3 = hashlib.sha256(binascii.unhexlify(step2)).hexdigest()
  82.  step4 = int(step1 + step3[:8] , 16)
  83.  return ''.join([t[step4/(58**l)%58] for l in range(100)])[::-1].lstrip('1')
  84.  
  85. def wiftonum(wifpriv):    #converts from WIF to numerical private key
  86.  return sum([t.index(wifpriv[::-1][l])*(58**l) for l in range(len(wifpriv))])/(2**32)%(2**256)
  87.  
  88. def validwif(wifpriv):    #validates WIF generated by converting it back and forth
  89.  return numtowif(wiftonum(wifpriv))==wifpriv
  90.  
  91. def b58encode(v):    #Encode a byte string to the Base58
  92.     base=len(t)
  93.     val=0    
  94.     for c in v:
  95.         val*=256
  96.         val+=ord(c)
  97.     result=""
  98.     while val:
  99.         (val,mod)=divmod(val,base)
  100.         result=t[mod]+result
  101.     pad=0
  102.     for c in v:
  103.         if c=="\0":
  104.             pad+=1
  105.         else:
  106.             break
  107.     return (t[0]*pad)+result
  108.  
  109. def pubtoaddy(puk): #converts uncompressed public key to public address
  110.     version=chr(0)      
  111.     h=hashlib.new("SHA256")
  112.     h.update(puk)    
  113.     s=h.digest()
  114.     h=hashlib.new("RIPEMD160")
  115.     h.update(s)
  116.     kh=version+h.digest()
  117.     h=hashlib.new("SHA256")
  118.     h.update(kh)
  119.     cs=h.digest()
  120.     h=hashlib.new("SHA256")
  121.     h.update(cs)
  122.     cs=h.digest()[:4]
  123.     adr=b58encode(kh+cs)
  124.     return adr
  125.  
  126. ###Enable to allow blockchain query:
  127. #def GetBCIbalance(query):
  128. #    url = 'https://blockchain.info/q/addressbalance/' + query
  129. #    json_obj = urllib2.urlopen(url)
  130. #    data = json.load(json_obj)
  131. #    return data  
  132.  
  133. def genwallet(): # the main generator
  134.     totalbalance = 0
  135.     walletname = "DEFAULTWALLET.txt"
  136.  
  137.     #################Change these############ GENERATOR SEEDS: Initial numerical private key and numerical increment between keys, thus: key chain
  138.     seedbtc=13787023450987234098623465093474584872345908273452360908908071097932145987679    # default seed = first numerical private key to use in generation
  139.     customincr = 10873345756478567985678956481319876234879623450    # default increment between private keys
  140.     ###################################################################################################################
  141.     customcount = 50    # default address count
  142.  
  143.     #######DO NOT MOVE###########Enable the following to have Prompt for custom filename,seed and customincr -- these two numbers are all you need with this scrip to recover all keys, so pick smart.
  144.     #customseed = input('Enter a seed number between 2^50 and 2^253: ') #Overrides default seed with prompt
  145.     #seedbtc = customseed
  146.     #customcount = input('How many wallets, 144 max: ')
  147.     #if customcount >> 144:
  148.     #    customcount = 144
  149.     #customincr = input('Enter an increment number between 2^3 and 2^116: ')
  150.     #walletname = raw_input('Pick a filename: ')
  151.     ########DO NOT MOVE##########You can also recover wallets made with this software with just the first two numerical private keys, prk2-prk1=customincr
  152.  
  153.     text_file = open(walletname, "w")      #creates new file to store all keys, change the name of this file after/during creation to NOT LOSE KEYS!!!
  154.     multn = 0    #don't change this or you'll have to remember it too!!! this is the multipier that spaces your private keys
  155.  
  156.     for looper in range(0,customcount):    # for each address
  157.         balance = 0
  158.         privKey = seedbtc+customincr*multn  # equals seedbtc on first run, then counts up by customincr. These are your numerical private keys.
  159.         multn=multn+1    #counter for customincr multiplier  
  160.         hexprkstr= '%x' % privKey    #removes 0x and 'L' for printing purposes
  161.         PublicKey = EccMultiply(GPoint,privKey)   #gets public key from Eliptic function
  162.         WIFKEY = numtowif(privKey)  #gets WIF
  163.         wifvalid = validwif(numtowif(privKey)) #checks if WIF validates by double conversion
  164.         ucpuk = "04" + "%064x" % PublicKey[0] + "%064x" % PublicKey[1];    #uncompressed public key
  165.  
  166.         if PublicKey[1] % 2 == 1:    #odd compressed public key
  167.             cpuk ="03"+str(hex(PublicKey[0])[2:-1]).zfill(64)
  168.         else:                        #even compressed public key
  169.             cpuk ="02"+str(hex(PublicKey[0])[2:-1]).zfill(64)  
  170.  
  171.         PubAd = pubtoaddy(Hex2Byte(ucpuk))  #gets public address
  172.         #balance = float(GetBCIbalance(PubAd))/100000000; balchen = true       #Enable to do api balance check on blockchain.info
  173.         #totalbalance = totalbalance + balance   #tracks total balance for disabled query
  174.  
  175.         newhex = hexprkstr
  176.         for padhexpr in range (0, (64 - len(hexprkstr))):    #makes hex private key ready to copy
  177.             newhex = "0"+ newhex  # just padding left side with zeros until 64 characters
  178.         hexprkstr = newhex
  179.  
  180.         print >>text_file        
  181.         print >>text_file,"PublicAddress",looper+1,": ",PubAd#, " ",balance        #enable ', " ",balance' to print
  182.         print >>text_file,"NumericalPrivteKey: "
  183.         print >>text_file,"     ",privKey
  184.         print >>text_file,"HexPrivateKey: "
  185.         print >>text_file,"     ",hexprkstr
  186.         print >>text_file,"WalletImportFormat: "
  187.         print >>text_file,"     ",WIFKEY,"  :  Use this to validate"
  188.  
  189.         if wifvalid:
  190.             donothing=0   #does not print if WIF is valid
  191.         else:
  192.             print >>text_file,"     ","WIFValid: ",wifvalid     #prints if WIF is invalid  
  193.  
  194.         print >>text_file,"UncompressedPublicKey: "
  195.         print >>text_file,"     ",ucpuk
  196.         print >>text_file,"CompressedPublicKey: "
  197.         print >>text_file,"     ",cpuk
  198.        
  199.         print PubAd#, "  ",balance      #enable ', " ",balance' to print
  200.  
  201.     text_file.close()
  202.  
  203.     print "File has been created with", multn, "key sets."# + " Total balance of: ", totalbalance   #enable ' + " Total balance of: ", totalbalance' to print balance
  204.  
  205. genwallet() # Start Generator
  206.  
  207. ########################################This section enables restart
  208. #newwalletstart = "y"
  209. #yesido = "y"
  210. #while newwalletstart is yesido:
  211. #    newwalletstart = raw_input('Create another wallet? y, else close:')
  212. #    if newwalletstart is yesido:
  213. #        genwallet()
  214. #########################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement