Commits

Tanel Liiv committed dfb68e1

Initial

Comments (0)

Files changed (1)

+class IDEA(object):
+    def __init__(self, key, text):
+        # key and text are both hex strings
+        self.key = key
+        self.text = text
+        self._keyindex = 0
+        
+        assert len(self.text) is 16
+        assert len(self.key) is 32
+    
+    def encrypt(self):
+        # main rounds
+        text = self._text_distributor()
+        key = self._key_distributor()
+        for y in xrange(0,8):
+            print y,
+            x = self._idea_round(text.next(),
+                text.next(),
+                text.next(),
+                text.next(),
+                key.next(),
+                key.next(),
+                key.next(),
+                key.next(),
+                key.next(),
+                key.next())
+            self.text = "".join(map(lambda x: hex(x)[2:].rjust(4, '0'), x))
+
+        # final round
+        print "last", 
+        print self.text
+        x = self._last_round(text.next(),
+            text.next(),
+            text.next(),
+            text.next(),
+            key.next(),
+            key.next(),
+            key.next(),
+            key.next())
+        self.text = "".join(map(lambda x: hex(x)[2:].rjust(4, '0'), x))
+        print "Text", self.chunk(self.text, 4)
+            
+        print self.text
+        
+    def decrypt(self):
+        pass
+        
+    def _idea_round(self, p0, p1, p2, p3, k0, k1, k2, k3, k4, k5):
+        #print "arguments", hex(p0), hex(p1), hex(p2),hex(p3), hex(k0), hex(k1), hex(k2),hex(k3), hex(k4), hex(k5)
+        mult_1 = self._mult(p0, k0)
+        add_1 = self._add(p1, k1)
+        add_2 = self._add(p2, k2)
+        mult_2 = self._mult(p3, k3)
+        
+        xor_1 = self._xor(mult_1, add_2)
+        xor_2 = self._xor(mult_2, add_1)
+        
+        mult_3 = self._mult(xor_1, k4)
+        add_3 = self._add(xor_2, mult_3)
+        
+        mult_4 = self._mult(add_3, k5)
+        add_4 = self._add(mult_3, mult_4)
+
+        xor_4 = self._xor(add_2, mult_4)
+        xor_3 = self._xor(mult_4, mult_1)
+
+        xor_5 = self._xor(add_1, add_4)
+        xor_6 = self._xor(add_4, mult_2)
+        
+        #print xor_3, "xor3", mult_4, mult_1
+        #print xor_4, "xor4", add_2, mult_4
+        #print xor_5, "xor5", add_1, add_4
+        #print xor_6, "xor6", add_4, mult_2
+        print "xors", xor_3, xor_4, xor_5, xor_6
+        return xor_3, xor_4, xor_5, xor_6
+        
+    def _last_round(self, p0, p1, p2, p3, k0, k1, k2, k3):
+        print "last round input", p0, p1, p2, p3, k0, k1, k2, k3
+        mult_1 = self._mult(p0, k0)%2**16
+        add_1 = self._add(p2, k1)
+        add_2 = self._add(p1, k2)
+        mult_2 = self._mult(p3, k3)%2**16
+        print "last round output", mult_1, add_1, add_2, mult_2
+        return mult_1, add_1, add_2, mult_2
+
+    def _mult(self, p, k):
+        if not p:
+            p = 2**16
+        if not k:
+            k = 2**16
+        #print ">>>", p, k
+        x = (p*k) % (2**16+1)
+
+        return x
+    
+    def _add(self, p, k):
+        return (p+k) % (2**16)
+
+    # foreign
+    def _xor(self, p, k):
+        return (p^k) % 2**16
+    
+    def _key_distributor(self):
+        counter = 0
+        step = 4
+        while counter < 208:
+            yield int(self.key[counter%32:counter%32+step], base=16)
+            counter += step
+            if not counter%32:
+                # permute the main key
+                self._key_scheduler()
+                #print self.key
+    
+    def _text_distributor(self):
+        counter = 0
+        step = 4
+        while counter < 144:
+            yield int(self.text[counter%16:counter%16+step], base=16)
+            counter += step
+    
+    def _key_scheduler(self):
+        self.key = (hex(self.rol(int(self.key, base=16), 25, 128)).replace('L', "")[2:]).rjust(32, '0')
+        print "Key",self.chunk(self.key, 4)
+        
+    def _rotate_shift(self, number, count):
+        # -25 is 25 shifts to the left
+        
+        #x = deque(list(bin(number)[2:]))
+        #print "old","".join(list(x))
+        #x.rotate(count)
+        #print "new", "".join(list(x))
+        #return int("".join(list(x)), base=2)
+        return number << 1
+    
+    def chunk(self, input, size):
+        return map(None, *([iter(input)] * size))
+    
+    def rol(self, n, rotations, width):
+        """Return a given number of bitwise left rotations of an integer n,
+           for a given bit field width.
+        """
+        rotations %= width
+        if rotations < 1:
+            return n
+        n &= self.mask(width) ## Should it be an error to truncate here?
+        return ((n << rotations) & self.mask(width)) | (n >> (width - rotations))
+    
+    def mask(self,n):
+        """Return a bitmask of length n (suitable for masking against an
+            int to coerce the size to a given length)
+        """
+        if n >= 0:
+            return 2**n - 1
+        else:
+            return 0
+
+x = IDEA("451C3E67448115D4E355CA9A0861247D", "8ED66B29DA624248")
+x.encrypt()