Skip to content

Instantly share code, notes, and snippets.

@laurent-leconte
Created October 13, 2023 13:44
Show Gist options
  • Save laurent-leconte/42be0d1c8cc999ccf1b168c85f978ced to your computer and use it in GitHub Desktop.
Save laurent-leconte/42be0d1c8cc999ccf1b168c85f978ced to your computer and use it in GitHub Desktop.
Simple number obfuscator
from secrets import randbelow
from typing import List
def decode(s: str) -> int:
"""
Grab the last 2 bits of each char in the string and turn
them into a number.
"""
res = 0
acc = 1
for c in s:
res += acc * (ord(c) & 3) # take the last two bits of the char
acc *= 4
return res
def encode(n: int, min_length=10) -> str:
"""
Take a number and encode it in a string, 2 bits per char.
The string is meant to be printable; chars are generated in the
0x24 ("$") to 0x7b ("{") range.
The generated string will be at least `min_length` chars long.
"""
res: List[str] = []
while n > 0 or len(res) < min_length:
base = randbelow(0x80 - 0x24) + 0x24 # 0x24 to 0x7b inclusive
base &= ~3 # make sure the last two bits are 0
res.append(chr(base + (n & 3))) # add the last two bits of n to the new char
n //= 4
return "".join(res)
secrets = [0, 1, 42, 2**20 - 1, 2**20]
secrets.extend(randbelow(2**20) for _ in range(10))
for secret in secrets:
encoded = encode(secret)
print(secret, encoded)
assert secret == decode(encoded)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment