Ok, e se riesci a trovare un modo per velocizzare il tutto fammi sapere!
It was the Bitcointalk forum that inspired us to create Bitcointalksearch.org - Bitcointalk is an excellent site that should be the default page for anybody dealing in cryptocurrency, since it is a virtual gold-mine of data. However, our experience and user feedback led us create our site; Bitcointalk's search is slow, and difficult to get the results you need, because you need to log in first to find anything useful - furthermore, there are rate limiters for their search functionality.
The aim of our project is to create a faster website that yields more results and faster without having to create an account and eliminate the need to log in - your personal data, therefore, will never be in jeopardy since we are not asking for any of your data and you don't need to provide them to use our site with all of its capabilities.
We created this website with the sole purpose of users being able to search quickly and efficiently in the field of cryptocurrency so they will have access to the latest and most accurate information and thereby assisting the crypto-community at large.
x = 0000000000000000000000000000000000000000000000000000000000000001
y = 4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee
x = 000000000000aeea7a7a5c04504f6e4e45452940431c9a264011686f3b746f92
x = 00000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63
'0'*(64+2+1-len(hex(ax)))
print ('Public key : ' + '0'*(64+2+1-len(hex(ax))) + hex(ax)[2:-1] + ' ' + hex(ay)[2:-1])
x = 0000000000000000000000000000000000000000000000000000000000000001
y = 4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee
x = 000000000000aeea7a7a5c04504f6e4e45452940431c9a264011686f3b746f92
x = 00000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63
python2 genadd.py 0x03
Private key : 0000000000000000000000000000000000000000000000000000000000000003
Public key : f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9 388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672
PrKey WIF u.: 5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreB1FQ8BZ
Address u. : ec7eced2c57ed1292bc4eb9bfd13c9f7603bc338
Address u. : 1NZUP3JAc9JkmbvmoTv7nVgZGtyJjirKV1
PrKey WIF c.: KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74sHUHy8S
Address c. : 7dd65592d0ab2fe0d0257d571abf032cd9db93dc
Address c. : 1CUNEBjYrCn2y1SdiUMohaKUi4wpP326Lb
#!/usr/bin/env python
#genera indirizzo
import hashlib, binascii
import sys
####__ECC COMPUTATION__####################################################
Gx=0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
Gy=0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
p=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F #caratteristica del campo
n=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 #ordine della curva
#calcola l'inverso di a modulo p --> a^-1
#a e' un numero compreso tra 1 e p-1
#p e' un numero primo
#vedi http://www.springer.com/?SGWID=4-102-45-110359-0 pag.40 algoritmo 2.20
def inv(a,p):
u, v = a%p, p
x1, x2 = 1, 0
while u != 1 :
q = v//u
r = v-q*u
x = x2-q*x1
v = u
u = r
x2 = x1
x1 = x
return x1%p
#test: stampa l'inverso di 3 modulo 7
#print inv(3,7)
def aff_to_jac(ax, ay):
jax, jay, jaz = ax, ay, 1
return jax, jay, jaz
def jac_to_aff(jax, jay, jaz):
invjaz=inv(jaz,p)
ax, ay = (jax*invjaz**2) % p, (jay*invjaz**3) % p
return ax, ay
#https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
#coordinate jacobiane
def add(jax, jay, jaz, jbx, jby, jbz):
u1 = (jax*jbz**2) % p
u2 = (jbx*jaz**2) % p
s1 = (jay*jbz**3) % p
s2 = (jby*jaz**3) % p
h = (u2-u1) % p
r = (s2-s1) % p
jcx = (r**2 -h**3-2*u1*h**2) % p
jcy = (r*(u1*h**2-jcx)-s1*h**3) % p
jcz = (h*jaz*jbz) % p
return jcx, jcy, jcz
def double(jax, jay, jaz):
s = (4*jax*jay**2) % p
m = (3*jax**2) % p
jax2 = (m**2 - 2*s) % p
jay2 = (m*(s-jax2) - 8*jay**4) % p
jaz2 = (2*jay*jaz) % p
return jax2, jay2, jaz2
def mul(d,jax,jay,jaz):
dax, day, daz = 0, 0, 1
if (d%2 == 1):
dax, day, daz = jax, jay, jaz #solo se d e' dispari
q=d//2
while q>0:
jax, jay, jaz = double(jax,jay,jaz)
if (q%2 > dax): #puo' succedere solo se dax=0 e q%2=1 cioe' la prima volta
dax, day, daz = jax, jay, jaz #solo se d e' pari
elif (q%2):
dax, day, daz = add(jax, jay, jaz, dax, day, daz)
q=q//2
return dax, day, daz
########################################################################
# 58 character alphabet used
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
__b58base = len(__b58chars)
def b58encode(v): #encode v, which is a string of bytes, to base58.
long_value = 0
if bytes == str: # python2
for (i, c) in enumerate(v[::-1]):
long_value += ord(c) << (8*i) # 2x speedup vs. exponentiation
else: # python3
for (i, c) in enumerate(v[::-1]):
long_value += ord(chr(c)) << (8*i) # 2x speedup vs. exponentiation
result = ''
while long_value >= __b58base:
div, mod = divmod(long_value, __b58base)
result = __b58chars[mod] + result
long_value = div
result = __b58chars[long_value] + result
# Bitcoin does a little leading-zero-compression:
# leading 0-bytes in the input become leading-1s
nPad = 0
if bytes == str: # python2
for c in v:
if c == '\0': nPad += 1
else: break
else: # python3
for c in v:
if chr(c) == '\0': nPad += 1
else: break
return (__b58chars[0]*nPad) + result
###########################################################################
######## PRIVATE KEY #####################################
pr=int(sys.argv[1],16)
#print (pr)
print ('Private key : ' + hex(pr)[2:].rstrip('L').rjust(64,'0'))
######## PUBLIC KEY ######################################
jax, jay, jaz = mul(pr,Gx,Gy,1)
ax, ay = jac_to_aff(jax, jay, jaz)
print ('Public key : ' + hex(ax)[2:].rstrip('L').rjust(64,'0') + ' ' + hex(ay)[2:].rstrip('L').rjust(64,'0'))
####################################################################################
#### PRIVATE KEY WIF UNCOMPRESSED (start with 5, 51 car.) ##########################
#pr=int(sys.argv[1],16)
#print ('Private key : ' + '0'*(64+2-len(hex(pr))) + hex(pr)[2:])
pr_wif = '80' + hex(pr)[2:].rstrip('L').rjust(64,'0') #primo passaggio: aggiungi 80
#print (pr_wif)
pr1=binascii.unhexlify(pr_wif)
h=hashlib.new('sha256') #secondo passaggio: sha256 di 80+pr
h.update(pr1)
#print h.hexdigest()
pr2=binascii.unhexlify(h.hexdigest())
h2=hashlib.new('sha256')
h2.update(pr2) #terzo passaggio: sha256(sha256(80+pk))
#print h2.hexdigest()
pr3=pr_wif+h2.hexdigest()[:8] #quarto passaggio: aggiungere primi 4 byte del terzo passaggio a pr_wif
#print (pr3)
pr_wif=b58encode(binascii.unhexlify(pr3)) #ultimo passaggio: codifica in base 58
print (' ')
print ('PrKey WIF u.: ' + pr_wif)
###############ADDRESS UNCOMPRESSED###########################
pk = '04' + hex(ax)[2:].rstrip('L').rjust(64,'0') + hex(ay)[2:].rstrip('L').rjust(64,'0')
#pk = '0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001'
pkb=binascii.unhexlify(pk)
#pkb = 'bitcoin'
h=hashlib.new('sha256') #secondo passaggio: sha256 di pk
h.update(pkb)
#print h.hexdigest()
r=hashlib.new('ripemd160') #terzo passaggio: ripmed160 di pk
r.update(h.digest())
#print r.hexdigest()
pk4='00'+r.hexdigest() #quarto passaggio: aggiungere byte 00
pk5=binascii.unhexlify(pk4) #quinto passaggio: sha256 di pk4
h2=hashlib.new('sha256')
h2.update(pk5)
#print h2.hexdigest()
h3=hashlib.new('sha256')
h3.update(h2.digest()) #sesto passaggio: sha256 di pk
#print h3.hexdigest()
pk7=pk4+h3.hexdigest()[:8] #settimo/ottavo passaggio: sha256 di pk
#print (pk7)
print ('Address u. : ' + pk7[2:-8])
address=b58encode(binascii.unhexlify(pk7)) #ultimo passaggio: codifica in base 58
print ('Address u. : ' + address)
####################################################################################
#### PRIVATE KEY WIF COMPRESSED (start with a, K or L, 52 car.) ##########################
pr_wif_c = '80' + hex(pr)[2:].rstrip('L').rjust(64,'0') +'01' #primo passaggio: aggiungi 80 e 01
#print (pr_wif_c)
pr1=binascii.unhexlify(pr_wif_c)
h=hashlib.new('sha256') #secondo passaggio: sha256 di 80+pr
h.update(pr1)
#print h.hexdigest()
pr2=binascii.unhexlify(h.hexdigest())
h2=hashlib.new('sha256')
h2.update(pr2) #terzo passaggio: sha256(sha256(80+pk))
#print h2.hexdigest()
pr3=pr_wif_c+h2.hexdigest()[:8] #quarto passaggio: aggiungere primi 4 byte del terzo passaggio a pr_wif
#print pr3
pr_wif_c=b58encode(binascii.unhexlify(pr3)) #ultimo passaggio: codifica in base 58
print ('')
print ('PrKey WIF c.: ' + pr_wif_c)
#########ADDRESS COMPRESSED##########################################
if (ay % 2) == 0:
pk = '02' + hex(ax)[2:].rstrip('L').rjust(64,'0') #formato compresso - caso y pari
else:
pk = '03'+ hex(ax)[2:].rstrip('L').rjust(64,'0') #formato compresso - caso y dispari
#pk = '020000000000000000000000000000000000000000000000000000000000000001'
#pk = '0200000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63'
#pkb =
pkb=binascii.unhexlify(pk)
h=hashlib.new('sha256') #secondo passaggio: sha256 di pk
h.update(pkb)
#print h.hexdigest()
#print (h.hexdigest())
r=hashlib.new('ripemd160') #terzo passaggio: ripmed160 di pk
r.update(h.digest())
#print r.hexdigest()
pk4='00'+r.hexdigest() #quarto passaggio: aggiungere byte 00
pk5=binascii.unhexlify(pk4) #quinto passaggio: sha256 di pk4
h2=hashlib.new('sha256')
h2.update(pk5)
#print h2.hexdigest()
h3=hashlib.new('sha256')
h3.update(h2.digest()) #sesto passaggio: sha256 di pk
#print h3.hexdigest()
pk7=pk4+h3.hexdigest()[:8] #settimo/ottavo passaggio: sha256 di pk
#print (pk7)
print ('Address c. : ' + pk7[2:-8])
address=b58encode(binascii.unhexlify(pk7)) #ultimo passaggio: codifica in base 58
print ('Address c. : ' + address)
k= 36028797808045092L
i=2
for i in range(0,2049): #endomorphism + the complement private keys
...
(kmx1,kmx2)=batch2[i]
(kmy1,kmy2)=batch_minus[i]
kmx2=mpz(379959518814287045958648687471962984512966710861088625468824313811360031883L)
kmy2=mpz(92747954983170185218682381260230771573227638080083976457265008071145396556169L)
kmx1=mpz(7201604086710695650663508557402304478547658998818769447222340328578603507969L)
kmy1=mpz(31566297453090183625880834540517108001193318981570045279173760792728274893122L)
#!/usr/bin/env python
#this script computes 6x667 batchs of 4097 points (1 single point + 2048 couples of points -> (kG+mG, kG-mg))
#16,4 millions of points
#3 : 1 batch + 5 endomorphism
import datetime
from ecc_for_collider05 import *
from KeyHelper import *
from random import randint
def generateConsecutiveAddresses(lowest_key,batches):
totFaulty=0
#print("Begin:" + str(datetime.datetime.now()))
########################################################################
#in this section the script pre-computes 1G, 2G, 3G, ..., 2048G
mG = [(0,0)]*2049
mGx = [0]*2049
mGy = [0]*2049
mGx[1]=Gx
mGy[1]=Gy
mG[1]=(Gx,Gy) #list of multiples of G,
#you have to precompute and store these multiples somewhere
mGx[2]=mpz(0xC6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5)
mGy[2]=mpz(0x1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A)
mG[2]=(mGx[2],mGy[2])
for i in range(3,2049):
jx,jy,jz=add_j_j(Gx, Gy, mpz(1), mGx[i-1], mGy[i-1], mpz(1)) #this is not a efficient way, but it is not important
jzinv = inv(jz,p)
(x,y) = jac_to_aff(jx, jy, jz, jzinv)
mG[i] = (x,y)
mGx[i] = x
mGy[i] = y
###########################################################################
lowest_key=lowest_key #put here the lowest key you want to generate
number_of_batches=batches # #put here how many consecutive batches you want to generate
number_of_keys=4097*6*number_of_batches #this is the number of consecutive keys you are going to generate
#this number is always a multiple of 6*4097=24582, because 24582 is the minimum size
#remember: you generate always 6 batches at once, 1 in (1,2^160) and 5 out of this range
#their name are: main_batch (the main), batch2, batch3, batch_minus
#(these other batches are derived from the main with endomorphism or complement private keys)
id_batch=lowest_key+2048 #id_batch is now the private key of the middle point of the first batch that you want compute
distance_between_successive_batches=4097 #this is the distance from the middle point of the first batch and the middle point
#of the successive batch in (1,2^160)
#4097 means that I'm generating only consecutive batches in (1,2^160), this is the default
start=id_batch #the first key to generate of the the first batch is the lowest key + 2048 -->
#the middle point of the first batch
stop=id_batch + number_of_batches*distance_between_successive_batches #the key of the middle point of the last batch
#k is always the id of the current main batch and the key of the middle point of the current main batch
for k in range(start,stop,distance_between_successive_batches):
jkx,jky,jkz = mul(k,Gx,Gy,mpz(1)) #here we use the slow function mul to generate the middle point
#invjkz = inv(jkz,p)
invjkz=gmpy2.invert(jkz,p) # 1I
(kx,ky) = jac_to_aff(jkx, jky, jkz, invjkz)
kminverse = [0]*2048
kminverse = inv_batch(kx,mGx,p) #you need to compute 2048 inverse, 1 for each couple
#to perform this task you need only the x coordinates of the multiples of G and
#the x coordinate of kG: kx
kminverse = [invjkz]+kminverse
#the element number 0 of the list is the inverse invjkz that you have computed to get kG=(kx,ky)
#the element number 1 of the list is the inverse necessary to perform kG + 1G (and kG-1G)
#---> 1/(x_of_1G - kx)
#the element number 2 of the list is the inverse necessary to perform kG + 2G (and kG-2G)
#---> 1/(x_of_2G - kx)
#...
#the element number m of the list is the inverse necessary to perform kG + mG (and kG-mG)
#---> 1/(x_of_mG - kx)
#then the name: "kminverse", the inverse to get the generic kG+mG
#...
#the element number 2048 of the list is the inverse necessary to perform kG+2048G and kG-2048G
#---> 1/(x_of_2048G - kx)
main_batch=[(0,0,0,0)]*2048
#the element number 0 of the list will be the middle point kG=(kx,ky), you can see it as the couple ((k+0)G, (k-0)G)
#the element number 1 will be the couple (k+1)G, (k-1)G
#the element number 2 will be the couple (k+2)G, (k-2)G
#...
#the element number 2048 will be the couple (k+2048)G, (k-2048)G
#each element of this list is a couple of points -> 4 scalars: x_(k+m)G,y_(k+m)G,x_(k-m)G,y_(k-m)G,
#but the first element is only a fake couple
main_batch = double_add_P_Q_inv(kx,ky,mG,kminverse)
#_the function double_add_P_Q_inv computes kG +/-mG, it uses the list of the inverse and return a list of couple of points
#each element of this list is a couple of points, 4 scalars, x_(k+m)G,y_(k+m)G,x_(k-m)G,y_(k-m)G
#this list has 2049 elements
main_batch = [(kx,ky,kx,ky)]+main_batch #the element number 0 of the list is now the middle point kG=(kx,ky), you can see it as the fake couple (k+0)G, (k-0)G
batch2=[0] * 2049 #this is the batch2 with lambda*kG, ( lambda*(k+1)G, lambda*(k-1)G ), ( lambda*(k+2)G, lambda*(k-2)G ), ....,
# (lambda*(k+2048)G, lambda*(k-2048)G)
#this list actually has only the x-cooordinates of the points, because the y-coordinates are the same of main batch
#each element of this list is a couple of x -> 2 scalars: x_lambda*(k+m)G, x_lambda*(k-m)G
#this list has 2049 elements
batch3=[0] * 2049 #this is the batch3 with lambda^2*kG, ( lambda^2*(k+1)G, lambda^2*(k-1)G ), ( lambda^2*(k+2)G, lambda^2*(k-2)G ), ....,
# (lambda^2*(k+2048)G, lambda^2*(k-2048)G)
#this list actually has only the x-cooordinates of the points, because the y-coordinates are the same of main batch
#each element of this list is a couple of x -> 2 scalars: x_lambda^2*(k+m)G, x_lambda^2*(k-m)G
#this list has 2049 elements
batch_minus=[0] * 2049 #the complement private keys of the other batches
for i in range(0,2049): #endomorphism + the complement private keys
x1,y1,x2,y2=main_batch[i]
batch2[i] = [(x1*beta % p), (x2*beta % p)] #only x coordinates, the first and the third scalar of each element
#of the main batch
#private key: lambda*k mod n, coordinate x: beta*x mod p
batch3[i] = [(x1*beta2 % p), (x2*beta2 % p)] #only x coordinates, the first and the third scalar of each element
#of the main batch
#private key: lambda^2*k mod n, coordinate x: beta^2*x mod p
batch_minus[i]=[(-y1 % p), (-y2 % p)] #only y coordinates, the 2^ and the 4^ scalar of each element of all batches
(kmx1,kmx2)=batch2[i]
(kmy1,kmy2)=batch_minus[i]
address = generateAddress(uncompressedKey(hex(kmx1), hex(kmy1)))
if address == "":
totFaulty = totFaulty+1
address = generateAddress(uncompressedKey(hex(kmx2), hex(kmy2)))
if address == "":
totFaulty = totFaulty+1
a=number_of_keys//1000000
#print ('You have just generated ' + str(a) + ' Millions of keys!!!')
#print("End:" + str(datetime.datetime.now()))
print ("Faulty coordinates: " + str(totFaulty))
generateConsecutiveAddresses(2**55+789079076,667)
import binascii
import hashlib
import base58
def uncompressedKey(xcoord, ycoord):
#compressedkey="04" + xcoord[2:66] + ycoord[2:66]
ukey="04" + xcoord[2:66] + ycoord[2:66]
return ukey;
def hash160(hex_str):
sha = hashlib.sha256()
rip = hashlib.new('ripemd160')
sha.update(hex_str)
rip.update( sha.digest() )
#print ( "key_hash = \t" + rip.hexdigest() )
return rip.hexdigest() # .hexdigest() is hex ASCII
def generateAddress(publicKey):
#print ( "len " + str(len(publicKey)))
if(len(publicKey) < 130):
return ""
hex_str = bytearray.fromhex(publicKey)
# Obtain key:
key_hash = '00' + hash160(hex_str)
# Obtain signature:
sha = hashlib.sha256()
sha.update( bytearray.fromhex(key_hash) )
checksum = sha.digest()
sha = hashlib.sha256()
sha.update(checksum)
checksum = sha.hexdigest()[0:8]
address = base58.b58encode( bytes(bytearray.fromhex(key_hash + checksum)) )
#print ( "bitcoin address = \t" + address )
return address.decode("utf-8")
$ time python2 gen_batches_points08.py
private key: -lambda*(k+m)G
0x2a7fb67883ea214c0a96f75b449fa3cec8e1b0d1f1e65e8aa80c3ef6cffaa1ae
('0x1c98a16eb218925feea48547a41d9d07bbd757d696857b4c2072bd264c827938', '0x49963b55d6a149f0df12d4acd5065e26b3e9d4f7da9c56aab690f44e866afe16')
*******
private key: -lambda*(k-m)G
0x6554827e46f82b9e6c571fdc6ae54b90dfdd38c4a3daf5213f3b4ee41119b8f8
('0x3c8250f180d59f9f1deeb55dbe00deb835de8a774c2fe1e6231b9eb44cdb3148', '0x7fcc26c9d9b58dd0971e87dd475c9d535a393cd5cf2cc62d53d4130cef611b6b')
*******
You have just generated 16 Millions of keys!!!
real 0m6,460s
user 0m6,456s
import gmpy2
from gmpy2 import mpz
#see http://www.secg.org/sec2-v2.pdf at page 9
#Gx=55066263022277343669578718895168534326250603453777594175500187360389116729240
#Gy=32670510020758816978083085130507043184471273380659243275938904335757337482424
#p=115792089237316195423570985008687907853269984665640564039457584007908834671663
#n=115792089237316195423570985008687907852837564279074904382605163141518161494337
Gx=mpz(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)
Gy=mpz(0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
p=mpz(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) # Fp
n=mpz(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141) # E(Fp)
#endomorphism
lambd=mpz(0x5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72) # (lambda^3 = 1 mod n)
lambd2=mpz(0xac9c52b33fa3cf1f5ad9e3fd77ed9ba4a880b9fc8ec739c2e0cfc810b51283ce) #(lambda^2)
beta=mpz(0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee) # (beta^3 = 1 mod p)
beta2=mpz(0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40) # (beta^2)
############################################################################################
###Field operations
#a must be a number between 1 and p-1; input: a output: 1/a
#see http://www.springer.com/?SGWID=4-102-45-110359-0 page 40 alg. 2.20
def inv(a,p):
u, v = a%p, p
x1, x2 = 1, 0
while u != 1:
#q = v//u
#r = v-q*u
q, r = divmod(v,u)
x = x2-q*x1
v = u
u = r
x2 = x1
x1 = x
return x1%p
#inverse of a batch of x
#input: batch of x : [x1,x2,x3,x4,x5,x6,x7,x8,...,x2048]
#x is known (x of kG)
#output: batch of inverse: 1/(x1-x), 1/(x2-x), 1/(x3-x), ....
#3M for each inverse
def inv_batch(x,batchx,p):
a = (batchx[1]-x) % p
partial= [0]*2049
partial[1]=a
for i in range(2,2049):
a = (a*(batchx[i]-x)) % p #2047M
partial[i]=a
inverse=gmpy2.invert(partial[2048],p) # 1I
#inverse=inv(partial[2048],p) # 1I
batch_inverse=[0]*2049
for i in range(2048,1,-1):
batch_inverse[i-1]=(partial[i-1]*inverse) % p #2047M
inverse=(inverse*(batchx[i]-x)) %p #2047M
batch_inverse[0]=inverse
return batch_inverse
############################################################################################
##Group operations
# https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Point_addition
#'double' addition
#add 2 points P and Q --> P+Q
#add 2 points P and Q --> P-Q
#
#(X1,Y1) + (X2,Y2) --> (X3,Y3) (the inverse of (x2-x1) must be known)
#(X1,Y1) + (X2,-Y2) --> (X4,Y4) (the inverse of (x2-x1) must be known)
#
#input: (X1,Y1), (X2,Y2), the inverse of (X2 - X1): 5 scalars
#output: (X3,Y3), (X4,Y4) : 4 scalars
#4M + 2S
def double_add_P_Q_inv(x1, y1, batchG, batchinvx2x1):
batch=[0]*2048
for i in range(1,2049):
x2,y2 = batchG[i]
invx2x1 = batchinvx2x1[i]
dy = (y2-y1) #% p
a = dy*invx2x1 % p #1M
a2 = a**2 #1S
x3 = (a2 - x1 -x2) % p
y3 = (a*(x1-x3) -y1) % p #1M
dy = p-(y2+y1) #% p # only the sign of y2 changes, "y of -Q = -y of +Q"
a = dy*invx2x1 % p #1M x2 and then the inverse invx2x1 are the same
a2 = a**2 #1S
x4 = (a2 - x1 -x2) % p
y4 = (a*(x1-x4) -y1) % p #1M
batch[i-1]=(x3,y3,x4,y4)
return batch
#https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
#jacobian coordinates
def add_j_j(jax, jay, jaz, jbx, jby, jbz):
u1 = (jax*jbz**2) % p
u2 = (jbx*jaz**2) % p
s1 = (jay*jbz**3) % p
s2 = (jby*jaz**3) % p
h = (u2-u1) % p
r = (s2-s1) % p
jcx = (r**2 -h**3-2*u1*h**2) % p
jcy = (r*(u1*h**2-jcx)-s1*h**3) % p
jcz = (h*jaz*jbz) % p
return jcx, jcy, jcz
def double_j_j(jx, jy, jz):
s = (4*jx*jy**2) % p
m = (3*jx**2) % p
jx2 = (m**2 - 2*s) % p
jy2 = (m*(s-jx2) - 8*jy**4) % p
jz2 = (2*jy*jz) % p
return jx2, jy2, jz2
def mul(k,jx,jy,jz):
jkx, jky, jkz = 0, 0, 1
if (k%2 == 1):
jkx, jky, jkz = jx, jy, jz #only if d is odd
q=k//2
while q>0:
jx, jy, jz = double_j_j(jx,jy,jz)
a=q%2
if (a > jkx):
jkx, jky, jkz = jx, jy, jz #only if d is even
elif (a):
jkx, jky, jkz = add_j_j(jx, jy, jz, jkx, jky, jkz)
q=q//2
return jkx, jky, jkz
############################################################################################
#Coordinates
#from jacobian to affine
def jac_to_aff(jax, jay, jaz, invjaz):
ax, ay = (jax*invjaz**2) % p, (jay*invjaz**3) % p
return ax, ay
#!/usr/bin/env python
#this script computes 6x667 batchs of 4097 points (1 single point + 2048 couples of points -> (kG+mG, kG-mg))
#16,4 millions of points
#3 : 1 batch + 5 endomorphism
from ecc_for_collider08 import *
########################################################################
#in this section the script pre-computes 1G, 2G, 3G, ..., 2048G
mG = [(0,0)]*2049
mGx = [0]*2049
mGy = [0]*2049
mGx[1]=Gx
mGy[1]=Gy
mG[1]=(Gx,Gy) #list of multiples of G,
#you have to precompute and store these multiples somewhere
mGx[2]=mpz(0xC6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5)
mGy[2]=mpz(0x1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A)
mG[2]=(mGx[2],mGy[2])
for i in range(3,2049):
jx,jy,jz=add_j_j(Gx, Gy, mpz(1), mGx[i-1], mGy[i-1], mpz(1)) #this is not a efficient way, but it is not important
jzinv = inv(jz,p)
(x,y) = jac_to_aff(jx, jy, jz, jzinv)
mG[i] = (x,y)
mGx[i] = x
mGy[i] = y
###########################################################################
lowest_key=2**55+789079076 #put here the lowest key you want to generate
number_of_batches=667 # #put here how many consecutive batches you want to generate
number_of_keys=4097*6*number_of_batches #this is the number of consecutive keys you are going to generate
#this number is always a multiple of 6*4097=24582, because 24582 is the minimum size
#remember: you generate always 6 batches at once, 1 in (1,2^160) and 5 out of this range
#their name are: main_batch (the main), batch2, batch3, batch_minus
#(these other batches are derived from the main with endomorphism or complement private keys)
id_batch=lowest_key+2048 #id_batch is now the private key of the middle point of the first batch that you want compute
distance_between_successive_batches=4097 #this is the distance from the middle point of the first batch and the middle point
#of the successive batch in (1,2^160)
#4097 means that I'm generating only consecutive batches in (1,2^160), this is the default
start=id_batch #the first key to generate of the the first batch is the lowest key + 2048 -->
#the middle point of the first batch
stop=id_batch + number_of_batches*distance_between_successive_batches #the key of the middle point of the last batch
#k is always the id of the current main batch and the key of the middle point of the current main batch
for k in range(start,stop,distance_between_successive_batches):
jkx,jky,jkz = mul(k,Gx,Gy,mpz(1)) #here we use the slow function mul to generate the middle point
#invjkz = inv(jkz,p)
invjkz=gmpy2.invert(jkz,p) # 1I
(kx,ky) = jac_to_aff(jkx, jky, jkz, invjkz)
kminverse = [0]*2048
kminverse = inv_batch(kx,mGx,p) #you need to compute 2048 inverse, 1 for each couple
#to perform this task you need only the x coordinates of the multiples of G and
#the x coordinate of kG: kx
kminverse = [invjkz]+kminverse
#the element number 0 of the list is the inverse invjkz that you have computed to get kG=(kx,ky)
#the element number 1 of the list is the inverse necessary to perform kG + 1G (and kG-1G)
#---> 1/(x_of_1G - kx)
#the element number 2 of the list is the inverse necessary to perform kG + 2G (and kG-2G)
#---> 1/(x_of_2G - kx)
#...
#the element number m of the list is the inverse necessary to perform kG + mG (and kG-mG)
#---> 1/(x_of_mG - kx)
#then the name: "kminverse", the inverse to get the generic kG+mG
#...
#the element number 2048 of the list is the inverse necessary to perform kG+2048G and kG-2048G
#---> 1/(x_of_2048G - kx)
main_batch=[(0,0,0,0)]*2048
#the element number 0 of the list will be the middle point kG=(kx,ky), you can see it as the couple ((k+0)G, (k-0)G)
#the element number 1 will be the couple (k+1)G, (k-1)G
#the element number 2 will be the couple (k+2)G, (k-2)G
#...
#the element number 2048 will be the couple (k+2048)G, (k-2048)G
#each element of this list is a couple of points -> 4 scalars: x_(k+m)G,y_(k+m)G,x_(k-m)G,y_(k-m)G,
#but the first element is only a fake couple
main_batch = double_add_P_Q_inv(kx,ky,mG,kminverse)
#_the function double_add_P_Q_inv computes kG +/-mG, it uses the list of the inverse and return a list of couple of points
#each element of this list is a couple of points, 4 scalars, x_(k+m)G,y_(k+m)G,x_(k-m)G,y_(k-m)G
#this list has 2049 elements
main_batch = [(kx,ky,kx,ky)]+main_batch #the element number 0 of the list is now the middle point kG=(kx,ky), you can see it as the fake couple (k+0)G, (k-0)G
batch2=[0] * 2049 #this is the batch2 with lambda*kG, ( lambda*(k+1)G, lambda*(k-1)G ), ( lambda*(k+2)G, lambda*(k-2)G ), ....,
# (lambda*(k+2048)G, lambda*(k-2048)G)
#this list actually has only the x-cooordinates of the points, because the y-coordinates are the same of main batch
#each element of this list is a couple of x -> 2 scalars: x_lambda*(k+m)G, x_lambda*(k-m)G
#this list has 2049 elements
batch3=[0] * 2049 #this is the batch3 with lambda^2*kG, ( lambda^2*(k+1)G, lambda^2*(k-1)G ), ( lambda^2*(k+2)G, lambda^2*(k-2)G ), ....,
# (lambda^2*(k+2048)G, lambda^2*(k-2048)G)
#this list actually has only the x-cooordinates of the points, because the y-coordinates are the same of main batch
#each element of this list is a couple of x -> 2 scalars: x_lambda^2*(k+m)G, x_lambda^2*(k-m)G
#this list has 2049 elements
batch_minus=[0] * 2049 #the complement private keys of the other batches
for i in range(0,2049): #endomorphism + the complement private keys
x1,y1,x2,y2=main_batch[i]
batch2[i] = [(x1*beta % p), (x2*beta % p)] #only x coordinates, the first and the third scalar of each element
#of the main batch
#private key: lambda*k mod n, coordinate x: beta*x mod p
batch3[i] = [(x1*beta2 % p), (x2*beta2 % p)] #only x coordinates, the first and the third scalar of each element
#of the main batch
#private key: lambda^2*k mod n, coordinate x: beta^2*x mod p
batch_minus[i]=[(-y1 % p), (-y2 % p)] #only y coordinates, the 2^ and the 4^ scalar of each element of all batches
#k in this case is the id of the last batch (or if you prefer, k is the private key of the middle point of the last batch)
m=2048 #a random number between 0 and 2048, you can pick up a couple of points in the last main batch (or in batch2 / batch3)
(kmx1,kmx2)=batch2[m]
(kmy1,kmy2)=batch_minus[m] #in this case the points chosen are in batch3
#the y are from batch_minus
#(kmx1,kmy1,kmx2,kmy2)=main_batch[m]
print ('private key: -lambda*(k+m)G')
print (hex(-lambd*(k+m)%n)) #private key
print (hex(kmx1), hex(kmy1)) #public key (first and second coordinate)
print ('*******')
print ('private key: -lambda*(k-m)G')
print (hex(-lambd*(k-m)%n)) #private key
print (hex(kmx2), hex(kmy2)) #public key (first and second coordinate)
print ('*******')
print (' ')
a=number_of_keys//1000000
print ('You have just generated ' + str(a) + ' Millions of keys!!!')