bcrypt.ctf/bcrypter/hash/rev.py

59 lines
1.5 KiB
Python

'''
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