Looks like those who is searching for #66 are at 354d range, even myself also search at the same range. If my research correct, #66 range should be in between 354df - 358ae. Even this range will take ages to scan. LoL.
How did you come to this conclusion?
By breaking down bits and some bits combination. Maybe just some wild guessing and not sure if I am correct because I spots seems like some obvious pattern. I hope someone can find it on this range thought even if I don't get it. If the results were in this range, then I can use the same methods to proceed to 67. Unfortunately, the most lowest I can go is only on current range. I guess it boost some morale maybe I am right when I saw zahid8888 post PK start at 354d and have similarity on #66 Hash160.
Anybody here familiar with Kangaroo? I have 1 stupid question. If let's say I put 1 million public address to search for private key and there's only 1 valid public address that fit the range. Will it take much more longer time to find the valid public key to get the private key? I tried just now with 100,000 public address, but the average time to solve shown unchanged.
I tried to put 1001 key with 1000 false public key and 1 puzzle 35 key. Why kangaroo can't solve it? Does that mean we can only put 1 public key at a time?
You can't find low range keys with kangaroo, 35 bit total range is less than 35 billion keys, I have tried with low ranges, my kangaroos start dying very fast, I can't even say goodbye. 🤣
I think more public keys you place in target file more you lose speed, but the speed reduction is insignificant even with few thousands less or more keys.
Exactly. It dead kangaroo almost immediately when I start. I am just trying to figure out if Kangaroo able to search lots of fake key with 1 valid key at once because I have some idea to lower #130 bits down but need to do a lot of manual works.
Anybody here familiar with Kangaroo? I have 1 stupid question. If let's say I put 1 million public address to search for private key and there's only 1 valid public address that fit the range. Will it take much more longer time to find the valid public key to get the private key? I tried just now with 100,000 public address, but the average time to solve shown unchanged.
I tried to put 1001 key with 1000 false public key and 1 puzzle 35 key. Why kangaroo can't solve it? Does that mean we can only put 1 public key at a time?
You can't find low range keys with kangaroo, 35 bit total range is less than 35 billion keys, I have tried with low ranges, my kangaroos start dying very fast, I can't even say goodbye. 🤣
I think more public keys you place in target file more you lose speed, but the speed reduction is insignificant even with few thousands less or more keys.
I think it's quite significant but I haven't try till it solve. Will try later. For example I try with on #65 keys, it solve in less than 3 minutes. But when I put it with 100 fake keys and 1 real key, I run for 20 mins just now and it still didn't solve. I will try later to see how long it takes with 100 and 1000 keys with only 1 real key. Furthermore, I try with #64 keys while the range I set it on #65, it seems like kangaroo unable to solve it.
Update on 64. When I try to solve 64 Public Key but range setting at 65, it spends almost 5 times more with a correct range provided to search.
Update:
I don't think Kangaroo able to solve multiple address. Now I am trying to merge save file and see if it able to resolve.
He is joking.
Using 12 CPU cores for parallel search.
Public key: 02f6a8148a62320e149cb15c544fe8a25ab483a0095d2280d03b8a00a7feada13d time: 2.66 sec
import time
import os
import sys
import random
import gmpy2
from gmpy2 import mpz
from functools import lru_cache
from multiprocessing import Pool, cpu_count
modulo = gmpy2.mpz(115792089237316195423570985008687907853269984665640564039457584007908834671663)
order = gmpy2.mpz(115792089237316195423570985008687907852837564279074904382605163141518161494337)
Gx = gmpy2.mpz(55066263022277343669578718895168534326250603453777594175500187360389116729240)
Gy = gmpy2.mpz(32670510020758816978083085130507043184471273380659243275938904335757337482424)
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
PG = Point(Gx, Gy)
Z = Point(0, 0) # zero-point, infinite in real x,y-plane
def mul2(P, p=modulo):
c = (3 * P.x * P.x * pow(2 * P.y, -1, p)) % p
R = Point()
R.x = (c * c - 2 * P.x) % p
R.y = (c * (P.x - R.x) - P.y) % p
return R
def add(P, Q, p=modulo):
dx = Q.x - P.x
dy = Q.y - P.y
c = dy * gmpy2.invert(dx, p) % p
R = Point()
R.x = (c * c - P.x - Q.x) % p
R.y = (c * (P.x - R.x) - P.y) % p
return R
@lru_cache(maxsize=None)
def X2Y(X, y_parity, p=modulo):
Y = 3
tmp = 1
while Y:
if Y & 1:
tmp = tmp * X % p
Y >>= 1
X = X * X % p
X = (tmp + 7) % p
Y = (p + 1) // 4
tmp = 1
while Y:
if Y & 1:
tmp = tmp * X % p
Y >>= 1
X = X * X % p
Y = tmp
if Y % 2 != y_parity:
Y = -Y % p
return Y
def compute_P_table():
P = [PG]
for k in range(255):
P.append(mul2(P[k]))
return P
P = compute_P_table()
os.system('clear')
t = time.ctime()
sys.stdout.write("\033[01;33m")
sys.stdout.write(t + "\n")
sys.stdout.write("P-table prepared" + "\n")
sys.stdout.write("tame and wild herds is being prepared" + "\n")
sys.stdout.flush()
def comparator(A, Ak, B, Bk):
result = set(A).intersection(set(B))
if result:
sol_kt = A.index(next(iter(result)))
sol_kw = B.index(next(iter(result)))
print('total time: %.2f sec' % (time.time() - starttime))
difference = Ak[sol_kt] - Bk[sol_kw]
HEX = "%064x" % difference # Convert to a hexadecimal string
t = time.ctime()
print('SOLVED:', t, difference)
with open("KEYFOUNDKEYFOUND.txt", 'a') as file:
file.write('\n\nSOLVED ' + t)
file.write('\nPrivate Key (decimal): ' + str(difference))
file.write('\nPrivate Key (hex): ' + HEX)
file.write('\n-------------------------------------------------------------------------------------------------------------------------------------\n')
return True
else:
return False
def check(P, Pindex, DP_rarity, file2save, A, Ak, B, Bk):
if P.x % DP_rarity == 0:
A.append(P.x)
Ak.append(Pindex)
with open(file2save, 'a') as file:
file.write(('%064x %d' % (P.x, Pindex)) + "\n")
# Print the public key
message = "\rPublic key: {:064x}".format(P.x)
sys.stdout.write("\033[01;33m")
sys.stdout.write(message)
sys.stdout.flush()
return comparator(A, Ak, B, Bk)
else:
return False
# Memoization for ecmultiply
ecmultiply_memo = {}
def ecmultiply(k, P=PG, p=modulo):
if k == 0:
return Z
elif k == 1:
return P
elif k % 2 == 0:
if k in ecmultiply_memo:
return ecmultiply_memo[k]
else:
result = ecmultiply(k // 2, mul2(P, p), p)
ecmultiply_memo[k] = result
return result
else:
return add(P, ecmultiply((k - 1) // 2, mul2(P, p), p))
def mulk(k, P=PG, p=modulo):
if k == 0:
return Z
elif k == 1:
return P
elif k % 2 == 0:
return mulk(k // 2, mul2(P, p), p)
else:
return add(P, mulk((k - 1) // 2, mul2(P, p), p))
def search(Nt, Nw, puzzle, kangoo_power, starttime):
DP_rarity = 1 << ((puzzle - 2 * kangoo_power) // 2 - 2)
hop_modulo = ((puzzle - 1) // 2) + kangoo_power
T, t, dt = [], [], []
W, w, dw = [], [], []
for k in range(Nt):
t.append((3 << (puzzle - 2)) + random.randint(1, (1 << (puzzle - 1))))
T.append(mulk(t[k]))
dt.append(0)
for k in range(Nw):
w.append(random.randint(1, (1 << (puzzle - 1))))
W.append(add(W0, mulk(w[k])))
dw.append(0)
oldtime = time.time()
Hops, Hops_old = 0, 0
t0 = time.time()
oldtime = time.time()
starttime = oldtime
while True:
for k in range(Nt):
Hops += 1
pw = T[k].x % hop_modulo
dt[k] = 1 << pw
solved = check(T[k], t[k], DP_rarity, "tame.txt", T, t, W, w)
if solved:
return 'sol. time: %.2f sec' % (time.time() - starttime)
t[k] += dt[k]
T[k] = add(P[pw], T[k])
for k in range(Nw):
Hops += 1
pw = W[k].x % hop_modulo
dw[k] = 1 << pw
solved = check(W[k], w[k], DP_rarity, "wild.txt", W, w, T, t)
if solved:
return 'sol. time: %.2f sec' % (time.time() - starttime)
w[k] += dw[k]
W[k] = add(P[pw], W[k])
puzzle = 35
compressed_public_key = "02f6a8148a62320e149cb15c544fe8a25ab483a0095d2280d03b8a00a7feada13d" # Puzzle 35
kangoo_power = 9 #For Puzzle 50-56 use 9 to 11, for Puzzle 60-80 use 14 to 16 / 24 cores or above preferred
Nt = Nw = 2 ** kangoo_power
X = int(compressed_public_key, 16)
Y = X2Y(X % (2 ** 256), X >> 256)
if Y % 2 != (X >> 256) % 2:
Y = modulo - Y
X = X % (2 ** 256)
W0 = Point(X, Y)
starttime = oldtime = time.time()
Hops = 0
random.seed()
hops_list = []
N_tests = kangoo_power
for k in range(N_tests):
buffer_size = 1024 * 1024 * 1024 # 1024 MB in bytes
with open("tame.txt", 'w', buffering=buffer_size) as tame_file, open("wild.txt", 'w', buffering=buffer_size) as wild_file:
tame_file.write('')
wild_file.write('')
def parallel_search(process_count, Nt, Nw, puzzle, kangoo_power, starttime):
pool = Pool(process_count)
results = pool.starmap(search, [(Nt, Nw, puzzle, kangoo_power, starttime)] * process_count)
pool.close()
pool.join()
return results
if __name__ == '__main__':
process_count = cpu_count() # Use all available CPU cores
print(f"Using {process_count} CPU cores for parallel search.")
results = parallel_search(process_count, Nt, Nw, puzzle, kangoo_power, starttime)
for result in results:
print(result)