def recover_seed(ciphertext, known_text): known_length = len(known_text) padding = len(ciphertext) - known_length rounded_padding = padding % 4 if rounded_padding != 0: rounded_padding = 4 - rounded_padding # Start of our known text known_start = padding + rounded_padding known_end = padding + rounded_padding + 8 known = ciphertext[known_start:known_end] # Convert them to numbers which were generated by rng t = util.string_xor(known, known_text[-8:]) known_a = struct.unpack(">L", t[:4])[0] known_b = struct.unpack(">L", t[4:])[0] for i in xrange(65536): update_progress(i, 65536) mt = MersenneTwister(i) for ignore in xrange(padding/4): mt.next() for check in xrange(known_length + 5): if mt.next() == known_a: if mt.next() == known_b: return i return "FAILED"
def MtStream(textLen, seed): """Generates the stream of random bytes.""" generator = MersenneTwister(seed) stream = [] for i in range(0, textLen): stream.append(generator.randomNumber() % (2**8)) return stream
def CrackSeed(generatedNumber): currentTime = int(time.time()) for tries in range(0, 1000000): mt = MersenneTwister(currentTime) if mt.randomNumber() == generatedNumber: return currentTime currentTime -= 1 return None
def RandWithTimestampedSeed(): pause = random.randint(MIN_PAUSE, MAX_PAUSE) time.sleep(pause) seed = int(time.time()) # Just to know if we did it right. print('[**] Leaking the seed for verification purposes: ' + str(seed)) mt = MersenneTwister(seed) pause = random.randint(MIN_PAUSE, MAX_PAUSE) time.sleep(pause) return mt.randomNumber()
def is_in_stream(seed, token, max_output): mt = MersenneTwister(seed) stream = [] #get full token worth to compare with while len(stream) < len(token): stream.append(chr(mt.extract_number() % 256)) if stream == token: return True max_output -= len(stream) i = 0 while i < max_output: stream.pop(0) stream.append(chr(mt.extract_number() % 256)) if stream == token: return True i += 1 return False
def recover_key(known_pt, ct): prefix_len = len(ct) - len(known_pt) partial_key = xor(known_pt, ct[prefix_len:]) #try all partial 16 bit seeds for i in range((1 << 16)): mt = MersenneTwister(i) skip_output(mt, prefix_len) match = True #check to see if output matches for c in partial_key: if ord(c) != (mt.extract_number() % 256): match = False break if match: return i
def cipher(self, text, seed): self.mt = MersenneTwister(seed) enc = '' length = len(text) for c in xrange(0, length, 4): random_number = self.mt.next() random_bytes = struct.pack('>I', random_number) for i in xrange(4): if c + i == length: break enc += chr(ord(random_bytes[i]) ^ ord(text[c+i])) return enc
# How many characters in the ciphertext are random characters that # were prepended. We pretend we do not know what these characters # are. randomLen = len(ciphertext) - 14 internalState = [] # This gives the generated random numbers from randomLen on; we # cannot retrieve the first ones because we do not know the # associated plaintext characters. for ch in range(randomLen, len(ciphertext)): internalState += BlockXor(bytes([ciphertext[ch]]), b'X') # For each possible seed, we build a MT random generator, generate # numbers and compare them with the retrieve internal state. If # they match, we found the right seed. This takes at most 1-2 minutes # when the random seed is close to maxSeed. # # TODO: find a more efficient cracking way than bruteforce. for probableSeed in range(0, maxSeed): mt = MersenneTwister(probableSeed) reproducedState = [] for i in range(0, len(ciphertext)): reproducedState.append(mt.randomNumber() % (2**8)) if reproducedState[randomLen:] == internalState: print('[**] The cracked seed is: ', str(probableSeed)) break else: print('[!!] Could not crack seed.')
i = h << 7 k = y ^ (i & mask) return k def untemperD(y): a = y >> 11 b = y ^ a c = b >> 11 return y ^ c def untemper(n): n = untemperA(n) n = untemperB(n) n = untemperC(n) n = untemperD(n) return n def clone_mt(mt): state = [] for i in xrange(624): state.append(untemper(mt.next())) return ClonedMersenneTwister(state, 0) if __name__ == '__main__': mt = MersenneTwister(0) cmt = clone_mt(mt) for i in xrange(10): print "From cloned: %s, from original: %s" % (mt.next(), cmt.next())
def rng(): time.sleep(random.randint(42, 1024)) mt = MersenneTwister(int(time.time())) time.sleep(random.randint(42, 1024)) return mt.next()
x = y ^ z s = x >> 11 y = y ^ s return y def FindStateFromOutputs(realOutputs): state = [] isFirst = True for output in realOutputs: state.append(Untemper(output)) return state if __name__ == '__main__': realMt = MersenneTwister(10) realOutputs = [] for i in range(0, 624): realOutputs.append(realMt.randomNumber()) # Reconstruct the internal state array from the random outputs. state = FindStateFromOutputs(realOutputs) clonedMt = MersenneTwister(seed=10, injectedState=state) clonedOutputs = [] # Generates again all numbers depending on the current state # from the cloned generator. for i in range(0, 624): clonedOutputs.append(clonedMt.randomNumber())
temp = state[i] ^ state[(i + self.m) % self.n] # find leading bit if temp % 2: temp ^= self.a shifted = (temp << 1) & self.upper_mask temp = state[(i - 1) % self.n] ^ state[ (i + self.m - 1) % self.n] # ending bits of int if temp & self.upper_mask == self.upper_mask: # check if leading bit is the same temp ^= self.a shifted |= 1 state[i] = shifted ^ (temp << 1) & self.lower_mask return state if __name__ == "__main__": # this can also be used to crack floats if you scale and round them first random_32 = MersenneTwister() old_state_32 = random_32.getstate() outputs_32 = [random_32.random_integer() for _ in range(624)] cracker_32 = MersenneCracker() new_state_32 = cracker_32.crack_state(outputs_32) random_32.setstate([new_state_32, 0]) # start at beginning of state assert outputs_32 == [random_32.random_integer() for _ in range(624)] print("32-bit Successfully Cracked") assert cracker_32.untwist(new_state_32)[1:] == old_state_32[0][ 1:] # seed may be different print("32-bit Successfully Reversed") random_32_alt = MersenneTwister(variant="mt11213b") outputs_32_alt = [random_32_alt.random_integer() for _ in range(624)] cracker_32_alt = MersenneCracker(variant="mt11213b") new_state_32_alt = cracker_32_alt.crack_state(outputs_32_alt)
def encrypt(message, seed): mt = MersenneTwister(seed) return ''.join( [chr(ord(m) ^ (mt.extract_number() % 256)) for m in message])
def get_token2(): mt = MersenneTwister(int(time.time())) skip_output(mt, random_int16()) return [chr(mt.extract_number() % 256) for _ in range(8)]
def get_token(seed=int(time.time())): mt = MersenneTwister(seed) return ''.join([chr(mt.extract_number() % 256) for _ in range(8)])
import socket import os from mersenne_twister import MersenneTwister host = '' port = 50000 backlog = 5 size = 1024 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.bind((host,port)) s.listen(backlog) while 1: print("Started Server....") print("At port : %s with process id : %s " % (port,os.getpid())) client,address = s.accept() data = client.recv(size) if data: params=data.split("|") process_id =int(params[0]) num_of_rand = int(params[1]) print("Invoking MersenneTwister with process id : %s and number of random number : %s" % (process_id,num_of_rand)) rand_gen = MersenneTwister(process_id,num_of_rand) client.send(rand_gen.rand()) else: print("Incorrect input recieved from client") client.send("Unable to generate random number")