def encrypt_mt19937(seed, plaintext): assert (seed < 2**16) key_stream = bytearray() r = random(seed) while len(key_stream) < len(plaintext): key_stream.extend(int.to_bytes(r.random(), 4, byteorder='big')) return xor_bytes(plaintext, key_stream)
def get_output(): global secret_seed wait = pyrand.randint(40, 1000) sleep(wait / 100) # we're not *that* patient... now = time.time() secret_seed = int(now) print("Seed is: %d" % secret_seed) r = random(secret_seed) wait = pyrand.randint(40, 1000) sleep(wait / 100) # we're not *that* patient... return r.random()
from prng import random, clone_mt19937 rand = random(42) outputs = [rand.random() for _ in range(1000)] cloned = clone_mt19937(outputs) for _ in range(1000): assert(cloned.random() == rand.random())
from prng import random import random as pyrand from time import sleep import time # sanity check r = random(10) values1 = [r.random() for _ in range(1000)] r = random(10) values2 = [r.random() for _ in range(1000)] assert(values1 == values2) def get_output(): global secret_seed wait = pyrand.randint(40, 1000) sleep(wait / 100) # we're not *that* patient... now = time.time() secret_seed = int(now) print("Seed is: %d" % secret_seed) r = random(secret_seed) wait = pyrand.randint(40, 1000) sleep(wait / 100) # we're not *that* patient... return r.random() output = get_output() now = int(time.time())
from prng import random # See the notes on MT19937 as to why we're taking values generated by C++'s # std::mt19937 rather than Python's random. r = random(5) assert (r.random() == 953453411) for _ in range(1000): r.random() assert (r.random() == 2924403310)
from prng import random import random as pyrand from time import sleep import time # sanity check r = random(10) values1 = [r.random() for _ in range(1000)] r = random(10) values2 = [r.random() for _ in range(1000)] assert (values1 == values2) def get_output(): global secret_seed wait = pyrand.randint(40, 1000) sleep(wait / 100) # we're not *that* patient... now = time.time() secret_seed = int(now) print("Seed is: %d" % secret_seed) r = random(secret_seed) wait = pyrand.randint(40, 1000) sleep(wait / 100) # we're not *that* patient... return r.random() output = get_output() now = int(time.time())
from prng import random, clone_mt19937 rand = random(42) outputs = [rand.random() for _ in range(1000)] cloned = clone_mt19937(outputs) for _ in range(1000): assert (cloned.random() == rand.random())
def is_mt19937_token(token, time_window=300): seed = int(time()) return any( random(seed + time_diff).random() == token for time_diff in range(-time_window, time_window + 1))
def generate_mt19937_token(): seed = int(time()) return random(seed).random()
random(seed + time_diff).random() == token for time_diff in range(-time_window, time_window + 1)) assert (decrypt_mt19937(42, encrypt_mt19937(42, b"Hello World!")) == b"Hello World!") known_plaintext = b"A" * 14 # normally we want 16-bits, but it takes too long... the idea is the same here. secret_seed = int.from_bytes(urandom(1), byteorder='big') print("Secret seed is: %d" % secret_seed) hidden_prefix = urandom(urandom(1)[0]) hidden_plaintext = hidden_prefix + known_plaintext ciphertext = encrypt_mt19937(secret_seed, hidden_plaintext) valid_seeds = (seed for seed in range(2**16) if known_plaintext in decrypt_mt19937(seed, ciphertext)) assert (next(valid_seeds) == secret_seed) print("Found seed!") print("Generating token...") token = generate_mt19937_token() assert (is_mt19937_token(token)) print("Detected!") print("Generating fake token...") token = random(42).random() assert (not is_mt19937_token(token)) print("Detected!")