View difference between Paste ID: sYGhWgpj and RAhJ1guh
SHOW: | | - or go back to the newest paste.
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
172+
        #balance = float(GetBCIbalance(PubAd))/100000000;        #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
#########################################