k98kurz

tapehash.py

Jun 20th, 2022 (edited)
530
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.37 KB | None | 0 0
  1. from hashlib import (
  2.     sha256, md5,
  3.     shake_128, shake_256,
  4.     sha3_256, sha3_512,
  5.     blake2b, blake2s
  6. )
  7.  
  8.  
  9. """New randomized proof-of-work hashing algorithms inspired roughly by
  10.    XMR's RandomX but much simpler and shoddier.
  11.    From https://pastebin.com/xY3B3K8S
  12. """
  13.  
  14.  
  15. def tapehash1(preimage: bytes, code_size: int = 1024) -> bytes:
  16.     """Runs the tapehash 1 algorithm on the preimage and returns a
  17.        32-byte hash. Computational complexity is tuneable via the
  18.        code_size parameter.
  19.    """
  20.     if type(preimage) is not bytes:
  21.         raise TypeError('preimage must be bytes')
  22.  
  23.     # generate the code and the tape
  24.     code = shake_256(preimage).digest(code_size)
  25.     tape = bytearray(blake2b(preimage).digest())
  26.  
  27.     # run the program
  28.     for i in range(0, len(code)):
  29.         opcode = code[i] >> 4
  30.         pointer = ((code[i] << 4) % 256) >> 4
  31.  
  32.         tape = execute_opcode(opcode, pointer, tape)
  33.         tape = execute_opcode(opcode, pointer + 16, tape)
  34.         tape = execute_opcode(opcode, pointer + 32, tape)
  35.         tape = execute_opcode(opcode, pointer + 48, tape)
  36.  
  37.     return sha256(tape).digest()
  38.  
  39.  
  40. def tapehash2(preimage: bytes, tape_size_multiplier: int = 1024*32) -> bytes:
  41.     """Runs the tapehash2 algorithm on the preimage and returns a
  42.        32-byte hash. Memory complexity can be tuned via the
  43.        tape_size_multiplier parameter.
  44.    """
  45.     if type(preimage) is not bytes:
  46.         raise TypeError('preimage must be bytes')
  47.     if type(tape_size_multiplier) is not int:
  48.         raise TypeError('tape_size_multiplier must be an int between 1 and 65,536')
  49.     if tape_size_multiplier <= 0 or tape_size_multiplier > 65_536:
  50.         raise ValueError('tape_size_multiplier must be an int between 1 and 65,536')
  51.  
  52.     # generate the code and the tape
  53.     code = blake2b(preimage).digest()
  54.     tape = bytearray(shake_256(preimage).digest(tape_size_multiplier * 32))
  55.  
  56.     # run the program
  57.     for i in range(0, len(code), 2):
  58.         opcode = code[i] >> 4
  59.         pointer = ((code[i] << 4) % 256) >> 4
  60.         double_pointer = int.from_bytes(code[i:i+2], 'big') % tape_size_multiplier
  61.  
  62.         tape = execute_opcode(opcode, pointer + double_pointer * 32, tape)
  63.         tape = execute_opcode(opcode, pointer + 16 + double_pointer * 32, tape)
  64.  
  65.     return sha256(tape).digest()
  66.  
  67.  
  68. def rotate_tape(tape: bytearray, pointer: int) -> bytes:
  69.     """Rotates the tape so that the pointer-indexed byte is first."""
  70.     if not isinstance(tape, bytearray):
  71.         raise TypeError('tape must be bytearray')
  72.     if not isinstance(pointer, int):
  73.         raise TypeError('pointer must be int')
  74.     if len(tape) < 1:
  75.         raise ValueError('tape must not be empty')
  76.     if pointer < 0 or pointer >= len(tape):
  77.         raise ValueError('pointer must be a valid index of tape')
  78.  
  79.     new_tape = tape[pointer:]
  80.     new_tape.extend(tape[:pointer])
  81.     return bytes(new_tape)
  82.  
  83.  
  84. def execute_opcode(opcode: int, pointer: int, tape: bytearray) -> bytearray:
  85.     """Execute a single opcode."""
  86.     if type(opcode) is not int:
  87.         raise TypeError('opcode must be an int')
  88.     if type(pointer) is not int:
  89.         raise TypeError('pointer must be an int')
  90.     if type(tape) is not bytearray:
  91.         raise TypeError('tape must be bytearray')
  92.     if opcode < 0 or opcode > 15:
  93.         raise ValueError('opcode must be between 0 and 15')
  94.     if pointer < 0 or pointer >= len(tape):
  95.         raise ValueError('pointer must be a valid index of tape')
  96.  
  97.     operations = {
  98.         0: lambda data: data, # no op
  99.         1: lambda data: (data + 1) % 256,
  100.         2: lambda data: data - 1 if data > 0 else 255,
  101.         3: lambda data: data >> 1,
  102.         4: lambda data: (data << 1) % 256,
  103.         5: lambda data: data ^ 255,
  104.         6: lambda data: (data * 2) % 256,
  105.         7: lambda data: (data ** 2) % 256,
  106.         8: lambda data: (data // 2) % 256,
  107.         9: lambda data: ((data << 4) % 256) | (data >> 4),
  108.         10: lambda data: sha256(data).digest()[data[0] % 32],
  109.         11: lambda data: md5(data).digest()[data[0] % 16],
  110.         12: lambda data: shake_128(data).digest(data[0] + 1)[data[0]],
  111.         13: lambda data: sha3_256(data).digest()[data[0] % 32],
  112.         14: lambda data: sha3_512(data).digest()[data[0] % 64],
  113.         15: lambda data: blake2s(data).digest()[data[0] % 32]
  114.     }
  115.  
  116.     if opcode < 10:
  117.         tape[pointer] = operations[opcode](tape[pointer])
  118.     else:
  119.         tape[pointer] = operations[opcode](rotate_tape(tape, pointer))
  120.     return tape
  121.  
  122.  
  123. def license():
  124.     """Copyleft (c) 2022 k98kurz
  125.  
  126.        Permission to use, copy, modify, and/or distribute this software
  127.        for any purpose with or without fee is hereby granted, provided
  128.        that the above copyleft notice and this permission notice appear in
  129.        all copies.
  130.  
  131.        THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  132.        WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  133.        WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  134.        AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
  135.        CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  136.        OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  137.        NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  138.        CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  139.    """
  140.     return license.__doc__
Add Comment
Please, Sign In to add comment