Secretive
The app uses AES to encrypt messages, with keys generated from a Linear Congruential Generator (LCG). If we are able to find previously-generated values from the LCG, then we could find the keys used to encrypt the flag.
class Secretizer:
def __init__(self):
self._lcg = None
def init_app(self, app):
self._lcg = LCG(app.config["LCG_SEED"], app.config["LCG_A"],
app.config["LCG_C"], app.config["LCG_M"])
...
def _gen_new_key(self):
return map(lambda _: self._lcg.random(), range(4))
def secretize_msg(self, msg):
key = self._gen_new_key()
key_str = self._key_to_keystr(key)
cipher = AESCipher(key_str)
encrypted_msg = cipher.encrypt(msg)
return (encrypted_msg, key)The LCG implementation is as follows.
LCGs can be quite easily broken, allowing us to find the values of a, c and m. We need to submit two messages, so that we get a pair of keys and their corresponding LCG-generated values. This is sufficient for us to find the LCG parameters.
Now, we need to reverse the LCG to find previously-generated values.
To do this, note that we can reorder the LCG next-state equation and apply the modular inverse of a to find the previous value of x.
Starting from the most recently-generated value, we can work backwards to the first 4 generated values, which would be the key used to encrypt the flag.
With the key found, we can obtain the flag!

Last updated
Was this helpful?