''' This file reverse engineers and reconstructs the original "bcrypt" hash function for the CTF (stored in bcrypt/hash.py). This reconstructs implements, namely, precomputation of tables of values in the hashing. Allowing bulk computation of hashes to be significantly faster. ''' from array import array from typing import Optional # Constants H = 18446744073709551614 K = 59275109328752 M = 2**64 def Rjb(j: int, b: int) -> int: return b << j**2 def Rb(b: int) -> int: Rb = 0 for j in range(8): Rb ^= Rjb(j, b) return Rb ''' Reconstructed implementation of the "bcrypt" hash function by bpaul. NOTE: An optional precomputed R_table is permitted as an arguement. ''' def bcrypt(x: bytes, R_table: Optional[dict[int, int]] = None) -> int: h = -2 for i, b in enumerate(x): R = R_table[b] if R_table is not None else Rb(b) h = h**2 * (b+1) + ((K * (i+1)) ^ R) h %= M return h % M ''' Returns a hashmap (python dictionary) of b -> R(b) for all b such that: min <= b <= max ''' def calc_R_map(min: int = 0, max: int = 255) -> dict[int, int]: R_map = {} # b from min to max (inclusive) for b in range(min, max+1): R_map[b] = Rb(b) return R_map ''' Same as calc_R_map() but using an array not a hashmap. ''' def calc_R_array(min: int = 0, max: int = 255) -> array.array[int]: R_array = array('i', [0]*(max-min)) # b from min to max (inclusive) for b in range(min, max+1): R_array[b-min] = Rb(b) return R_array