updated 12/11/2023.
The Baby Step Giant Step (BSGS) algorithm is used to solve the discrete logarithm problem efficiently in a cyclic group. The algorithm works by breaking down the problem into two steps:
Baby Steps In this step, we calculate a list of baby steps by iteratively raising the generator g to different powers. We start with j = 0 and calculate g^j for values of j from 0 up to m-1 , where m is typically chosen as the square root of the group order n . We store each calculation in
1 bit per key, this is the highlight because it considerably minimizes the size of our database.
binary baby step2000000 Keys
#by mcdouglasx
import secp256k1 as ice
from bitstring import BitArray
print("creating Baby Step")
#create baby step
num = 2000000 # Keys number in Binary Babystep. same m in search script
Low_m= 20
lm= num // Low_m
Add = 1
Add_pub= ice.scalar_multiplication(Add)
res= ice.point_sequential_increment(lm, Add_pub)
binary = ''
for t in range (lm):
h= (res[t*65:t*65+65]).hex()
hc= int(h[2:], 16)
if str(hc).endswith(('0','2','4','6','8')):
A="0"
binary+= ''.join(str(A))
if str(hc).endswith(('1','3','5','7','9')):
A="1"
binary+= ''.join(str(A))
my_str = (BitArray(bin=binary))#bin=binary
binary_file = open('baby_steps__binary.bin', 'ab')
my_str.tofile(binary_file)
binary_file.close()
for i in range (1,Low_m):
print("stage: "+ str(i+1)+"/"+str(20))
lm_upub= ice.scalar_multiplication((lm*i))
res= ice.point_sequential_increment(lm, lm_upub)
binary = ''
for t in range (lm):
h= (res[t*65:t*65+65]).hex()
hc= int(h[2:], 16)
if str(hc).endswith(('0','2','4','6','8')):
A="0"
binary+= ''.join(str(A))
if str(hc).endswith(('1','3','5','7','9')):
A="1"
binary+= ''.join(str(A))
my_str = (BitArray(bin=binary))#bin=binary
binary_file = open('baby_steps__binary.bin', 'ab')
my_str.tofile(binary_file)
binary_file.close()
Giant Steps In this step, we perform giant steps by multiplying, this approach is efficient because it reduces the search space for the discrete logarithm from O(n) to O(sqrt(n)) , significantly speeding up the computation for large cyclic groups.
search script#@author: iceland, modified by @mcdouglasx
import time
import random
import bit
import os
import math
import sys
import secp256k1 as ice
import numpy as np
from bitstring import BitArray
##Pk: 33185509 puzzle #30
Target = '03057fbea3a2623382628dde556b2a0698e32428d3cd225f3bd034dca82dd7455a'
bs_file = 'baby_steps__binary.bin'
start = 0
end = 33554431
m = 2000000 # Keys number in Binary Babystep
Cm= 64
public_key = ice.pub2upub(Target).hex()
# =============================================================================
def pub2upub(pub_hex):
x = int(pub_hex[2:66],16)
if len(pub_hex) < 70:
y = bit.format.x_to_y(x, int(pub_hex[:2],16)%2)
else:
y = int(pub_hex[66:],16)
return bytes.fromhex('04'+ hex(x)[2:].zfill(64) + hex(y)[2:].zfill(64))
#find baby step file
valid = os.path.isfile(bs_file)
if valid == True:
print('\nFound the Baby Steps Table file: '+bs_file+'. Will be used directly')
file = bytes(np.fromfile(bs_file))
baby_steps= BitArray(file)
if valid == False:
print('\nNot Found '+bs_file+'. you must Create This File Now.' )
###############################################################################
st = time.time()
print('\n[+] Starting Program : Binary BSGS mode')
Q = pub2upub(public_key)
# We have to solve P = k.G, we know that k lies in the range ]k1,k2]
k1 = random.randint(start, end) # start from
k2 = k1 + m*m
print('Checking {0} keys from {1}'.format(m*m, k1))
k1G = ice.scalar_multiplication(k1)
mG = ice.scalar_multiplication(m)
st = time.time()
###############################################################################
def findkey(onePoint):
S = ice.point_subtraction(Q, k1G)
found = False
step = 0
while found is False and step<(1+k2-k1):
Sx_1= ice.point_sequential_increment(Cm, S)
binary = ''
for t in range (Cm):
h= (Sx_1[t*65:t*65+65]).hex()
hc= int(h[2:], 16)
if str(hc).endswith(('0','2','4','6','8')):
A="0"
binary+= ''.join(str(A))
if str(hc).endswith(('1','3','5','7','9')):
A="1"
binary+= ''.join(str(A))
b = BitArray(bin=binary)
c = bytes(b)
Sw =c
if b in baby_steps:
#
s = c
f = BitArray(baby_steps)
inx = f.find(s)
inx_1=str(inx).replace(",", "")
inx_0=str(inx_1).replace("(", "")
inx_2=str(inx_0).replace(")", "")
b = int(inx_2)
found = True
break
else:
# Giant step
S = ice.point_subtraction(S, mG)
step = step + m
if found == True:
#print("k1:",k1)
#print("step:",step)
#print("b:",b)
final_key = (k1 + step + b + 1)-1
else:
final_key = -1
return final_key
final_key = findkey(Q)
if final_key >0:
print("BSGS FOUND PrivateKey :",str(final_key))
data= open("win.txt", "a")
data.write("private key = "+str(final_key)+"\n")
data.write(str("Time Spent : {0:.2f} seconds".format(time.time()-st))+ "\n")
data.close()
else:
print('PrivateKey Not Found')
print(str("Time Spent : {0:.2f} seconds".format(time.time()-st)))
This script is just an idea, it is not intended to be fast.
Make your own version in C.
This is a modification of Iceland's work.