3.21 PREDICTING TIME-BASED RANDOMNESS
EXERCISE 3.21: PREDICTING TIME-BASED RANDOMNESS
Write an AES encryption program (or modify one of the others you’ve written for this chapter) that uses Python random number generator to generate keys. Use the seed method to explicitly configure the generator based on the current time using
time.time()
rounded to the nearest second. Then use this generator to create a key and encrypt some data. Write a separate program that takes the encrypted data as input and tries to guess the key. It should take a minimum time and a maximum time as a range and try iterating between these two points as seed values for random.
# ex3_21.py
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
import os
import random
import time
def encrypt_msg(msg: bytes) -> dict:
= round(time.time()) # rounded to the nearest second
current_time = random.Random(current_time)
r
= r.getrandbits(128).to_bytes(16, 'big')
key = r.getrandbits(128).to_bytes(16, 'big')
iv
= Cipher(
aesCipher =algorithms.AES(key=key),
algorithm=modes.CTR(nonce=iv),
mode=default_backend(),
backend
)= aesCipher.encryptor()
encryptor return {
"msg": msg,
"encrypted-msg": encryptor.update(msg) + encryptor.finalize(),
"key": key,
"iv": iv,
"current_time": current_time,
}
def hack_encrypted_msg(encrypted_msg: bytes, min_time: int, max_time: int, msg: bytes):
for possible_seed in range(min_time, max_time + 1):
= random.Random(possible_seed)
r = r.getrandbits(128).to_bytes(16, 'big')
possible_key = r.getrandbits(128).to_bytes(16, 'big')
possible_iv
= Cipher(
aesCipher =algorithms.AES(key=possible_key),
algorithm=modes.CTR(nonce=possible_iv),
mode=default_backend(),
backend
)= aesCipher.decryptor()
decryptor = decryptor.update(encrypted_msg)
possible_msg += decryptor.finalize()
possible_msg
if (possible_msg == msg):
# we have a hit.
return possible_key
if __name__ == '__main__':
= b'hello world how are you doing'
msg = encrypt_msg(
result =msg,
msg
)print("Hacked Key: ", hack_encrypted_msg(
=result['encrypted-msg'],
encrypted_msg=result['current_time']-30,
min_time=result['current_time'] + 30,
max_time=msg,
msg
))
print("Actual Key: ", result['key`'])
Moral of the story: 1. Cryptographic keys should have enough randomness in them. Otherwise they are useless.