Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """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)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement