init
This commit is contained in:
commit
897272d7c1
5 changed files with 167 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
__pycache__/
|
||||
5
NOTES
Normal file
5
NOTES
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Ideas:
|
||||
1. Given an empty string of bytes, bcrypt('') == H == 184467...
|
||||
So is there any way to "force rotate" back to H modulo M?
|
||||
2. Can I get h % M == 0? If so then could potentially control the
|
||||
next iteration value?
|
||||
29
bcrypt.ctf.py
Normal file
29
bcrypt.ctf.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
def hashfn(x: bytes) -> int:
|
||||
h = 18446744073709551614
|
||||
|
||||
for (i, b) in enumerate(x):
|
||||
h *= h * (b + 1)
|
||||
k = 59275109328752 * (i + 1)
|
||||
for j in range(8):
|
||||
k ^= b << (j * j)
|
||||
h += k
|
||||
h %= (2 ** 64)
|
||||
|
||||
return h
|
||||
|
||||
|
||||
print("It's not even worth trying, because bcrypt is perfect!")
|
||||
print("Whatever, it's your time that you're wasting anyway...")
|
||||
a = bytes(input("Message 1: "), 'utf-8')
|
||||
b = bytes(input("Message 2: "), 'utf-8')
|
||||
|
||||
if a != b and hashfn(a) == hashfn(b):
|
||||
flag = open('flag.txt').read()
|
||||
print(
|
||||
f"Congrats! Here's {len(flag)} characters of "
|
||||
f"text for your hours of hard work: {flag}"
|
||||
)
|
||||
elif a == b:
|
||||
print("Those are the same message...")
|
||||
else:
|
||||
print("Trivially false!")
|
||||
109
bcrypt/bcrypt.py
Normal file
109
bcrypt/bcrypt.py
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
from math import gcd
|
||||
from random import randint, randbytes
|
||||
|
||||
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
|
||||
|
||||
'''
|
||||
Returns a hashmap (python dictionary) of b -> R(b)
|
||||
for all b such that: min < b < max
|
||||
'''
|
||||
def precompute_R(min: int,
|
||||
max: int) -> dict[int, int]:
|
||||
b = min
|
||||
R_table = {}
|
||||
while b <= max:
|
||||
R_table[b] = Rb(b)
|
||||
b += 1
|
||||
return R_table
|
||||
|
||||
|
||||
def hashfn(x: bytes, R_table: dict[int, int]) -> int:
|
||||
h = -2
|
||||
for i in range(len((x))):
|
||||
b = x[i]
|
||||
h = h**2 * (b+1) + ((K * (i+1)) ^ R_table[b])
|
||||
h %= M
|
||||
return h % M
|
||||
|
||||
def bcrypt(x: bytes) -> int:
|
||||
h = 18446744073709551614
|
||||
|
||||
for (i, b) in enumerate(x):
|
||||
h *= h * (b + 1)
|
||||
k = 59275109328752 * (i + 1)
|
||||
for j in range(8):
|
||||
k ^= b << (j * j)
|
||||
h += k
|
||||
h %= (2 ** 64)
|
||||
|
||||
return h
|
||||
|
||||
def debug_hashes_eq(x: bytes, R_table: dict[int, int]) -> bool:
|
||||
return hashfn(x, R_table) == bcrypt(x)
|
||||
|
||||
def debug_test_random_hashes(trials: int,
|
||||
max_bytes: int = 16,
|
||||
quiet: bool = False) -> bytes | None:
|
||||
R_table = precompute_R(0, 255)
|
||||
for i in range(trials):
|
||||
# generate random bytes
|
||||
num_bytes = randint(0, max_bytes)
|
||||
x = randbytes(num_bytes)
|
||||
|
||||
# test the modified bcrypt with the original
|
||||
hash_test = hashfn(x, R_table)
|
||||
hash_bcrypt = bcrypt(x)
|
||||
if hash_test != hash_bcrypt:
|
||||
if not quiet:
|
||||
print(f'Your hashfn sucks, big mistake bucko!! (iter: {i})')
|
||||
print(hash_test)
|
||||
print(hash_bcrypt)
|
||||
print([str(b) for b in x])
|
||||
return x
|
||||
|
||||
if not quiet:
|
||||
print('Impeccable hashfn holy moly!!')
|
||||
return None
|
||||
|
||||
|
||||
def main() -> None:
|
||||
print(f'gcd(H,K): {gcd(H,K)}')
|
||||
print(f'gcd(H,M): {gcd(H,M)}')
|
||||
print(f'gcd(K,M): {gcd(K,M)}')
|
||||
if debug_test_random_hashes(10000) != None:
|
||||
R_table = precompute_R(0, 255)
|
||||
x = bytes(input('x: '), 'utf-8')
|
||||
hash_test = hashfn(x, R_table)
|
||||
hash_bcrypt = bcrypt(x)
|
||||
print(f'hashfn: {hash_test}')
|
||||
print(f'bcrypt: {hash_bcrypt}')
|
||||
|
||||
# a = bytes(input("A: "), 'utf-8')
|
||||
# b = bytes(input("B: "), 'utf-8')
|
||||
|
||||
# if a != b and hashfn(a) == hashfn(b):
|
||||
# print('*** YOU WIN ***')
|
||||
# elif a == b:
|
||||
# print('Idiot those are the same')
|
||||
# else:
|
||||
# print("Trivially false!")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print('\n[!] Received SIGINT')
|
||||
except EOFError:
|
||||
print('\n[!] Reached EOF')
|
||||
23
bcrypt/working/shifts.py
Normal file
23
bcrypt/working/shifts.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
from typing import Any
|
||||
|
||||
def clamp_pos(x: int):
|
||||
return x if x > 0 else 0
|
||||
|
||||
def lpad(x: Any, n: int, pad: chr = ' '):
|
||||
x = str(x)
|
||||
return clamp_pos(n - len(x))*pad + x
|
||||
|
||||
def debug_R(B: int):
|
||||
# B = int('1'*7, 2)
|
||||
for j in range(8):
|
||||
j_sq = j**2
|
||||
R_j = B << j_sq
|
||||
lpadbin_R_j = lpad(bin(R_j)[2:], 64, pad='0')
|
||||
print(f'{lpad(j_sq, 2)}: {lpadbin_R_j} {R_j}')
|
||||
|
||||
def main():
|
||||
B = int(input('B: '), 2)
|
||||
debug_R(B)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue