Max Hernandez

Laberinto - Ejemplo de Canvas en HTML5

jueves, 25 de octubre de 2012

CryptMT V3 Stream Cipher

Last week on information security and cryptography class we talk about stream ciphers, and our work for homework this week is  that we are suppose to chose one and talk about it and make an example of it.

CryptMT
Is a stream cipher submitted to eStream project that is a pseudorandom number generator for a stream cipher, wich is a combination of a F2-Linear genertor of a wordsize-integer sequence with a big state space and a filter with one word-size memory.

Any attack has not been fount until now.

My Code:

For this homework i made an example of the algorithm in a python script, it is just the pseudorandom generator of bits keystream using an intial Key and an initial number value of 128-bits. It generate 128-bits every execution of "next" method.

All the values are generated in the "next" function that is a succession of the T values int he Cryptmt class using the "R" and "S" function. Well all the code explain the algorithm and there it is:


#!/usr/bin/python

def split_number(n, chunks, bits): # parte numero de 128 bits en 4 de 32
       temp = []
       for i in range(chunks):
           temp.insert(0, n % (2**bits))
           n = n>>32

       return temp

def join_number(n, bits): #recibe un vector y la cantidad de bits 
    temp = 0
    for i in range(len(n)):
        n[i] = n[i]<<(i*bits)
        temp += n[i]
    return temp

def sum_bits(a, b, bits):
    if 128%bits != 0:
        print "Wrong choice of bits"
        return False

    nChunks = 128/bits

    a = split_number(a, nChunks, bits)
    b = split_number(b, nChunks, bits)

    temp = []

    for i in range( nChunks ):
        temp.append( (a[i] + b[i]) % (2**bits) )

    return join_number(temp, bits)

def subtraction_bits(a, b, bits): # A - B 
    if 128%bits != 0:
        print "Wrong choice of bits"
        return False

    nChunks = 128/bits

    a = split_number(a, nChunks, bits)
    b = split_number(b, nChunks, bits)

    temp = []

    for i in range( nChunks ):
        temp.append( (a[i] - b[i]) % (2**bits) )

    return join_number(temp, bits)    

def permutation_bits(x, pos, bits):
    if 128%bits != 0:
        print "Wrong choice of bits"
        return False

    nChunks = 128/bits
    x = split_number(x, nChunks, bits)
    x = [x[pos[0]], x[pos[0]], x[pos[0]], x[pos[0]]]

    return join_number(x, bits)

def shift_right_bits(x, n, bits): # entrada, cantidad de movimientos, bits
    if 128%bits != 0:
        print "Wrong choice of bits"
        return False

    nChunks = 128/bits
    x = split_number(x, nChunks, bits)
    temp = []

    for i in x:
           temp.append(i>>n)

    return join_number(temp, bits)

def constant_multiplication_bits(c, x, bits):
    if 128%bits != 0:
        print "Wrong choice of bits"
        return False

    nChunks = 128/bits
    x = split_number(x, nChunks, bits)
    temp = []

    for i in x:
           temp.append( (i*c)% (2**bits) )

    return join_number(temp, bits)

def multiplication_bits(a, b, bits):
    if 128%bits != 0:
        print "Wrong choice of bits"
        return False

    nChunks = 128/bits

    a = split_number(a, nChunks, bits)
    b = split_number(b, nChunks, bits)

    temp = []

    for i in range( nChunks ):
        temp.append( (a[i] * b[i]) % (2**bits) )

    return join_number(temp, bits)

def R(x, y): #integers
       bits = 32

       temp = constant_multiplication_bits(2, x, bits)
       second_temp = permutation_bits(y, [1,0,2,3], bits)^shift_right_bits(y, 11, bits)
       temp = multiplication_bits(second_temp , temp, 32)

       temp = sum_bits(temp, x, bits)
       temp = sum_bits(second_temp, x, bits)

       return temp

def S(x,y,z):
       bits = 32

       temp = sum_bits(x, y, bits)
       temp = permutation_bits(temp, [2,1,0,3], bits)

       second_temp = sum_bits(x, y, bits)
       second_temp = shift_right_bits(second_temp, 13, bits)

       temp = temp^second_temp

       return subtraction_bits(temp, z, bits)


class Cryptmt:

       def __init__(self, k , iv):
              self.K = k % (2**128)
              self.IV = iv % (2**128)

              T3 = join_number([846264, 979323, 265358, 314159], 32)
              T3 = sum_bits(T3, self.K, 32)

              self.T = [self.IV, self.K, self.IV, T3]

              self.a = split_number(self.K, 4, 32)
              temp = []

              for i in self.a:
                     temp.append( i | 1 )
              self.a = join_number(temp, 32)

              self.contador = 1

       def next(self):
              self.a = R( self.a, self.T[self.contador+2] )
              self.T.append( S( self.T[self.contador-1], self.T[self.contador+1], 0 ) )
              temp = self.T[self.contador]
              self.contador += 1

              return temp

def main():
    stream = Cryptmt(234242234234234235245243, 2345234654563)
    for i in range(10):
           print (i+1),  stream.next()

main()

Excecution: 
It generates ten 128-bis numebers expressed in its integer form:
 
kalavera@kalavera-VPCEB13EL:~/Dropbox/criptografia/cryptmt$ ./cryptmt.py 
1 234242234234234235245243
2 2345234654563
3 85946719830258479757052665010416044847
4 3530248465310590354493131339071488
5 101140093095655703567504962208073703383
6 1765124232655295177246565669535749
7 202255601058652553349682145451892999721
8 8
9 303357995651555790738063429960658885664
10 2

References:
http://eprint.iacr.org/2009/110.pdf
http://www.ecrypt.eu.org/stream/cryptmtp3.html 

1 comentario:

  1. Ortografía.... ._. La explicación fue muuuy poca. No hablas nada sobre lo de ataques o vulnerabilidades conocidas :/ Van 5 pts ya que sí trabajaste bastante con un código propio.

    ResponderBorrar