예제 #1
0
def generatePasswordToken():
    mt = MT19937(int(time()))
    rawOutput = b''
    for i in range(6):
        rawOutput += mt.extract_number().to_bytes(4, byteorder='big')
    b64Output = rawToBase64(rawOutput)
    return b64Output
예제 #2
0
def MTStreamCipher(seed, rawInput):
    mt = MT19937(seed)
    rawOutput = b''
    mtOut = 0
    for i in range(len(rawInput)):
        if (i % 4 == 0):
            mtOut = mt.extract_number()
        thisKey = (mtOut >> (8 * (3 - (i % 4)))) & 0xff
        rawOutput += (rawInput[i] ^ thisKey).to_bytes(1, byteorder='big')
    return rawOutput
예제 #3
0
def cloneMT(dolly):
    clone = MT19937(0)
    # Note that the call to extract_number() is going to
    # call dolly.generate_numbers(), mucking with dolly's MT values
    # before we get to untemper
    # thus, the returned clone will be identical to dolly's state after
    # this function is finished, not before
    for i in range(624):
        clone.MT[i] = untemper(dolly.extract_number())
    return clone
예제 #4
0
def recoverSeed(output, timeNow):
    # we're pretty sure that the seed is in the range (timeNow - 2005, timeNow)
    # but we'll push the range check out to 10000 just for fun
    for i in range(10000):
        #guess seed
        mt = MT19937(timeNow - i)
        #check seed
        if (output == mt.extract_number()):
            print("Seed: ", timeNow - i)
            return i
    print("Failed to recover seed")
    return -1
예제 #5
0
def checkPasswordToken(b64Token):
    rawToken = base64toRaw(b64Token)
    now = int(time())
    for i in range(-100, 100):  # +/- one hour
        mt = MT19937(now + i)
        mtOutput = b''
        for i in range(6):
            mtOutput += mt.extract_number().to_bytes(4, byteorder='big')
        if (rawToken == mtOutput):
            print("MT seed time = ", (now + i))
            return (now - i)
    return (-1)
예제 #6
0
def randFromTime():
    # * Seeds the RNG with the current Unix timestamp
    mt = MT19937(initialTime + delay1)
    #* Returns the first 32 bit output of the RNG.
    return mt.extract_number()
예제 #7
0
def test_mt():
    mt1 = MT19937(8675309)
    mt2 = MT19937(8675309)
    for i in range(10000):
        if (mt1.extract_number() != mt2.extract_number()):
            print("Fail MT test!")
예제 #8
0
# generator, and splice that state into a new instance of the MT19937
# generator.
def cloneMT(dolly):
    clone = MT19937(0)
    # Note that the call to extract_number() is going to
    # call dolly.generate_numbers(), mucking with dolly's MT values
    # before we get to untemper
    # thus, the returned clone will be identical to dolly's state after
    # this function is finished, not before
    for i in range(624):
        clone.MT[i] = untemper(dolly.extract_number())
    return clone


# How would you modify MT19937 to make this attack hard? What would
# happen if you subjected each tempered output to a cryptographic hash?
'''The root problem is that one can connect an output value to PRNG state.
Preventing an attacker from working backwards (output = sha256(y)) would prevent that...
However, given that (y) is 32 bits, the attacker could build a 4-billion-entry table to invert
such outputs.  A better solution would be to use, say, the last 4 bytes of MT has an AES key,
and then have (output = AES(y|000...00, key)).  The keyspace prevents the attacker from 
building the table.'''

if __name__ == "__main__":
    temperTest()
    dolly = MT19937(8675309)
    clone = cloneMT(dolly)
    for i in range(10000):
        if (dolly.extract_number() != clone.extract_number()):
            raise Exception("Clone failed")
    print("Clone succeeded")