"""EdPoW: proof-of-work using 32 byte seeds to generate Ed25519 key pairs where the public key matches some kind of difficulty metric. """ from nacl.signing import SigningKey from secrets import token_bytes from sys import argv from typing import Callable import difficulty def edpow(target: int, diff_calc_func: Callable[[bytes], int]) -> tuple[int, int, bytes, bytes]: """Find an Ed25519 keypair with a public key with a number of preceding null bits equal to the target & measured by the supplied difficulty function. """ # set up some variables target = int(target) count = 0 measured_difficulty = 0 seed = token_bytes(32) # generate keys until public key of >=specified difficulty found while measured_difficulty < target: sk = SigningKey(seed) measured_difficulty = diff_calc_func(bytes(sk.verify_key)) count += 1 new_seed = int.from_bytes(seed, 'little') - 1 seed = new_seed.to_bytes(32, 'little') if new_seed > 0 else token_bytes(32) return (count, measured_difficulty, seed, bytes(sk.verify_key)) def edpow_bits(target: str): """Runs edpow(target, difficulty.calculate).""" return edpow(int(target), difficulty.calculate) def edpow_tries(target: str): """Runs edpow(target, difficulty.calculate_linear).""" return edpow(int(target), difficulty.calculate_linear) def edpow_query(target: bytes): """Find an Ed25519 keypair with a public key that contains the target bytes.""" # set up some variables estimated_difficulty = difficulty.calculate_query_bytes(target, 32) count = 1 seed = token_bytes(32) sk = SigningKey(seed) # generate keys until public key contains target while target not in bytes(sk.verify_key): count += 1 new_seed = int.from_bytes(seed, 'little') - 1 seed = new_seed.to_bytes(32, 'little') if new_seed > 0 else token_bytes(32) sk = SigningKey(seed) return (count, estimated_difficulty, seed, bytes(sk.verify_key)) def license() -> str: """ISC License Copyleft (c) 2022, k98kurz Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyleft notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ return license.__doc__ def usage(name): print(f'usage: {name} [mode] [target] [-h]') print('\tmode\tb for preceding bits') print('\t\tt for number of tries') print('\t\tq for specific query bytestring') print('\t\tqc for calculating difficulty for a query bytestring') print('\ttarget\tinteger difficulty target') print('\t-h\tparse target as hexadecimal') def main(args): """Command line interface.""" # print usage if used incorrectly if len(args) < 3 or args[1] not in ('b', 't', 'q', 'qc'): usage(args[0]) return mode = args[1] # parse target as hexadecimal if necessary if len(args) == 4 and args[3] in ('-h', '--hex', 'h', 'hex'): target = bytes.fromhex(args[2]) if mode in ('b', 't'): target = int.from_bytes(target, 'little') else: target = args[2] if mode in ('b', 't') else bytes(args[2], 'utf-8') # switch on mode if mode == 'b': result = edpow_bits(target) print(f'{result[0]} tries, {result[1]} difficulty, seed={result[2].hex()}, pk={result[3].hex()}') elif mode == 't': result = edpow_tries(target) print(f'{result[0]} tries, {result[1]} difficulty, seed={result[2].hex()}, pk={result[3].hex()}') elif mode == 'q': result = edpow_query(target) print(f'{result[0]} tries, {result[1]} difficulty, seed={result[2].hex()}, pk={result[3].hex()}') elif mode == 'qc': print(f'{difficulty.calculate_query_bytes(target, 32)} tries') if __name__ == '__main__': main(argv)