The best way to get an overview of this project is to see it in action. Below, you will find an example treasure hunt generated for Hacktoberfest 2025. Try to solve this puzzle and have fun. There is some small surprise for the quickest solvers.
# generated with puzzle-generator 0.16.8
#
# https://pypi.org/project/puzzle-generator/
# https://github.com/vil02/puzzle_generator/
import base64
import hashlib
import hmac
import sys
import typing
BYTEORDER: typing.Literal["little", "big"] = "little"
def sign_bytes(in_bytes: bytes, in_key: bytes, params) -> bytes:
return hmac.digest(msg=in_bytes, key=in_key, **params)
def derive_key(**kwargs) -> bytes:
return hashlib.scrypt(**kwargs)
def split_data_and_signature(
in_bytes: bytes, signature_size: int
) -> tuple[bytes, bytes]:
if len(in_bytes) < signature_size:
raise ValueError("in_bytes is shorter than signature_size")
data = in_bytes[:-signature_size]
signature = in_bytes[-signature_size:]
return data, signature
def digest_size(params) -> int:
hasher = hashlib.new(params["digest"])
return hasher.digest_size
def xor_bytes(in_bytes: bytes, in_key: bytes) -> bytes:
"""xors the in_bytes with a sequence of bytes with in_key"""
return bytes(_d ^ _k for (_d, _k) in zip(in_bytes, in_key, strict=True))
def bytestr_to_bytes(in_str: str) -> bytes:
return base64.b64decode(in_str)
def bytes_to_int(in_bytes: bytes) -> int:
bytes_length = int(in_bytes[0])
if len(in_bytes) != bytes_length + 1:
raise ValueError("in_bytes has wrong structure")
return int.from_bytes(in_bytes[1:], byteorder=BYTEORDER)
def split(in_bytes: bytes) -> tuple[str, bytes]:
end_of_length = int(in_bytes[0]) + 1
str_as_bytes_len = bytes_to_int(in_bytes[:end_of_length])
end_of_str = end_of_length + str_as_bytes_len
str_as_bytes = in_bytes[end_of_length:end_of_str]
res_bytes = in_bytes[end_of_str:]
return str_as_bytes.decode(), res_bytes
def decrypt_data(
in_rest: bytes,
in_pass: str,
in_decrypt: typing.Callable[[bytes, bytes], bytes | None],
) -> None | tuple[str, bytes]:
res = in_decrypt(in_rest, in_pass.encode())
if res is None:
return None
return split(res)
def must_be_nonempty(in_list: list[bytes]) -> None:
if not in_list:
raise ValueError("in_list must be nonempty")
def get_decrypt(
proc_spices: list[bytes],
signature_spices: list[bytes],
scrypt_params,
signature_params,
) -> typing.Callable[[bytes, bytes], bytes | None]:
must_be_nonempty(proc_spices)
must_be_nonempty(signature_spices)
def _decrypt(in_bytes: bytes, in_pass: bytes) -> bytes | None:
for proc_spice in proc_spices:
key = derive_key(
password=in_pass + proc_spice, dklen=len(in_bytes), **scrypt_params
)
data = xor_bytes(in_bytes, key)
decrypted, signature = split_data_and_signature(
data, digest_size(signature_params)
)
if any(
sign_bytes(decrypted + _, in_pass, signature_params) == signature
for _ in signature_spices
):
return decrypted
return None
return _decrypt
def run_puzzle(
in_puzzle: tuple[str, bytes],
in_decrypt: typing.Callable[[bytes, bytes], bytes | None],
get_answer: typing.Callable[[], str],
) -> None:
question, rest = in_puzzle
print(question)
if rest:
this_pass = get_answer()
new_puzzle = decrypt_data(rest, this_pass, in_decrypt)
if new_puzzle is None:
print("This is a wrong answer. Try again!")
sys.exit(1)
else:
run_puzzle(new_puzzle, in_decrypt, get_answer)
_PUZZLE = (
"""What is 2024+1?""",
bytestr_to_bytes(
"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"
),
)
_PROC_SPICES = [
bytestr_to_bytes(_)
for _ in [
"Q9tE",
"LPnT",
"1fnP",
"V+3e",
"xmvp",
"HweU",
"CPUU",
"RhO0",
"QaHe",
"XXCL",
"jT+h",
"CV3b",
"MQ9T",
"Zosa",
"Yuiv",
"4yAy",
"gFk2",
"qX5t",
"dxEN",
"w7Wt",
]
]
_SIGNATURE_SPICES = [
bytestr_to_bytes(_)
for _ in [
"JAm2",
"4KfX",
"LsZ9",
"OW3H",
"64Py",
"MAw4",
"sMLN",
"TVS9",
"lL08",
"AECo",
"SwYf",
"Bd/p",
"ATJW",
"eY3G",
"dv8o",
"T3mh",
"TIh1",
"vDRJ",
"t43i",
"LRkq",
]
]
_SCRYPT_PARAMS = {
"n": 16384,
"r": 8,
"p": 1,
"maxmem": 29884416,
"salt": bytestr_to_bytes("4redAb7kz6ZZisSHk7RleA=="),
}
_SIGNATURE_PARAMS = {"digest": "sha3_512"}
_DECRYPT = get_decrypt(
_PROC_SPICES, _SIGNATURE_SPICES, _SCRYPT_PARAMS, _SIGNATURE_PARAMS
)
run_puzzle(_PUZZLE, _DECRYPT, input)
The challenge is still active: #355 (comment)
The best way to get an overview of this project is to see it in action. Below, you will find an example treasure hunt generated for Hacktoberfest 2025. Try to solve this puzzle and have fun. There is some small surprise for the quickest solvers.
Caution
I am just a random guy on the internet! Before running this code, please review it and consider running it using some online tool like:
https://www.onlinegdb.com/online_python_compiler