Created
October 13, 2023 13:44
-
-
Save laurent-leconte/42be0d1c8cc999ccf1b168c85f978ced to your computer and use it in GitHub Desktop.
Simple number obfuscator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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