Personal Encryptor with Nonbreakable Inforation-theoretic Security
Description
The Personal Encryptor with Nonbreakable Information-theoretic Security seems rock solid.
nc challs.rumble.host 17171The PoC's code is even available.
Solution
The encryption algorithm generates random bytes using os.urandom() and adds them to the position of the original character in the 63-character alphabet. Every 63 characters “wraps around” back to the original character.
def keygen(length):
key = ""
rnd_bytes = os.urandom(length)
for i in range(length):
pos = rnd_bytes[i] % len(ALPHABET)
key += ALPHABET[pos]
return key
...
def encrypt(key, msg):
assert len(key) == len(msg), "For Information-theoretic security the key needs to be as long as the msg."
ciphertext = ""
for i in range(len(msg)):
msg_c = msg[i]
key_c = key[i]
if msg_c not in ALPHABET:
ValueError(f"Can't encrypt char: {msg_c}")
msg_pos_c = ALPHABET.index(msg_c)
key_pos_c = ALPHABET.index(key_c)
new_pos = (msg_pos_c + key_pos_c) % len(ALPHABET)
ciphertext += ALPHABET[new_pos]
return ciphertextNotice that the bytes will range from 0 to 255, and given that each byte has an equal probability of being chosen, the original character, and the characters that follow, will have a slightly higher probability of ending up in the ciphertext.
We can obtain a maximum of 1000 ciphertexts, but we can simply reconnect any number of times to get more ciphertexts. If we do this enough times, we will naturally observe that at each position of the flag, the highest frequency character that appears in the ciphertext would be one of the 4 characters (original, and the 3 characters that follow) that have a higher probability of appearing in the ciphertext.
At this point, we would know what the flag roughly looks like. Since we are provided with the SHA256 hash of the flag, we can simply brute force the offsets to obtain the original flag.
There is only a maximum of combinations to try (the first 4 characters CSR{ are known, and the highest frequency character is at an offset of either +0, +1, +2 or +3 from the original message).

Last updated
Was this helpful?