#!/usr/bin/env python3 import bencode import sys import libnacl import struct from io import BytesIO import time from multiprocessing import Process, Array, Value def print_help(): print('usage: {} keyfile.private prefix numthreads'.format(sys.argv[0])) return 1 _zalpha = ['y', 'b', 'n', 'd', 'r', 'f', 'g', '8', 'e', 'j', 'k', 'm', 'c', 'p', 'q', 'x', 'o', 't', '1', 'u', 'w', 'i', 's', 'z', 'a', '3', '4', '5', 'h', '7', '6', '9'] def zb32_encode(buf): s = str() bits = 0 l = len(buf) idx = 0 tmp = buf[idx] while bits > 0 or idx < l: if bits < 5: if idx < l: tmp <<= 8 tmp |= buf[idx] & 0xff idx += 1 bits += 8 else: tmp <<= 5 - bits bits = 5 bits -= 5 s += _zalpha[(tmp >> bits) & 0x1f] return s def _gen_si(keys): e = keys[b'e'][32:] s = keys[b's'][32:] v = keys[b'v'] return {'e': e, 's': s, 'v': v} class AddrGen: def __init__(self, threads, keys, prefix): self._inc = threads self._keys = keys self._c = Value('i') self.sync = Array('i', 3) self._procs = [] self.prefix = prefix def runit(self): for ch in self.prefix: if ch not in _zalpha: print("invalid prefix, {} not a valid character".format(ch)) return None, None print("find ^{}.loki".format(self.prefix)) i = self._inc while i > 0: p = Process(target=self._gen_addr_tick, args=(self.prefix, abs( libnacl.randombytes_random()), abs(libnacl.randombytes_random()), _gen_si(self._keys))) p.start() self._procs.append(p) i -= 1 return self._runner() def _gen_addr_tick(self, prefix, lo, hi, si): print(prefix) fd = BytesIO() addr = '' enc = bencode.BCodec(fd) while self.sync[2] == 0: si['x'] = struct.pack('>QQ', lo, hi) fd.seek(0, 0) enc.encode(si) pub = bytes(fd.getbuffer()) addr = zb32_encode(libnacl.crypto_generichash(pub)) if addr.startswith(prefix): self.sync[2] = 1 self.sync[0] = hi self.sync[1] = lo return hi += self._inc if hi == 0: lo += 1 self._c.value += 1 def _print_stats(self): print('{} H/s'.format(self._c.value)) self._c.value = 0 def _joinall(self): for p in self._procs: p.join() def _runner(self): while self.sync[2] == 0: time.sleep(1) self._print_stats() self._joinall() fd = BytesIO() enc = bencode.BCodec(fd) hi = self.sync[0] lo = self.sync[1] si = _gen_si(self._keys) si['x'] = struct.pack('>QQ', lo, hi) enc.encode(si) pub = bytes(fd.getbuffer()) addr = zb32_encode(libnacl.crypto_generichash(pub)) return si['x'], addr def main(args): if len(args) != 3: return print_help() keys = None with open(args[0], 'rb') as fd: dec = bencode.BCodec(fd) keys = dec.decode() runner = AddrGen(int(args[2]), keys, args[1]) keys[b'x'], addr = runner.runit() if addr: print("found {}.loki".format(addr)) with open(args[0], 'wb') as fd: enc = bencode.BCodec(fd) enc.encode(keys) if __name__ == '__main__': main(sys.argv[1:])