from hashlib import sha256 from os import urandom import scrypt
flag = b"fakeflag"
# Convert the flag (in bytes) to bits bits = ''.join([bin(c)[2:].zfill(8) for c in flag]) print(bits) # Return an encrypted string based on the bit at a certain index def encrypt(index): assert(0 <= index < len(bits))
# Generate a random salt for the given index salt = urandom(32) # Depending on the bit value, hash the flag differently if bits[index] == '0': encrypted = scrypt.hash(flag, salt, 2 ** 16).hex() else: encrypted = sha256(flag + salt).hexdigest() return encrypted[:32]
if __name__ == "__main__": while True: try: print("Which bit would you like to query for?") bit_index = int(input(">>> ")) print(encrypt(bit_index)) except Exception: print("Something unexpected happened, please try again!")
0x2 Analysis
firstly, lets take look at how code works.
pad each character in the 8 bit string
get the bit given an index, encrypt flag using either sha256 or scrypt depending on the bit
return the first 32 value of encrypted flag
looks like we don't have any possible way of getting the flag.
However, since scrypt runs much slower than sha256, we can measure the time of encrypting flag. And then use time to figure out if the bit is 1 or 0.
if we measure the time, we can see scrypt is using 0.16705632209777832 seconds, while sha256 only using 0.0001506805419921875, which is 1000 times slower.
1 2 3 4 5 6 7 8 9 10
Which bit would you like to query for? >>> 0 0 0.16705632209777832 128 69adfaef506c83899a98cc3f670a0e5d Which bit would you like to query for? >>> 1 1 0.0001506805419921875 64 3dc8c8cfae15c453bc162cafecc27575 Which bit would you like to query for? >>>