Python TEA implementation

10,923

Solution 1

I fixed it. Here is working TEA implementation in python:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import sys
from ctypes import *

def encipher(v, k):
    y = c_uint32(v[0])
    z = c_uint32(v[1])
    sum = c_uint32(0)
    delta = 0x9e3779b9
    n = 32
    w = [0,0]

    while(n>0):
        sum.value += delta
        y.value += ( z.value << 4 ) + k[0] ^ z.value + sum.value ^ ( z.value >> 5 ) + k[1]
        z.value += ( y.value << 4 ) + k[2] ^ y.value + sum.value ^ ( y.value >> 5 ) + k[3]
        n -= 1

    w[0] = y.value
    w[1] = z.value
    return w

def decipher(v, k):
    y = c_uint32(v[0])
    z = c_uint32(v[1])
    sum = c_uint32(0xc6ef3720)
    delta = 0x9e3779b9
    n = 32
    w = [0,0]

    while(n>0):
        z.value -= ( y.value << 4 ) + k[2] ^ y.value + sum.value ^ ( y.value >> 5 ) + k[3]
        y.value -= ( z.value << 4 ) + k[0] ^ z.value + sum.value ^ ( z.value >> 5 ) + k[1]
        sum.value -= delta
        n -= 1

    w[0] = y.value
    w[1] = z.value
    return w

if __name__ == "__main__":
    key = [1,2,3,4]
    v = [1385482522,639876499]
    enc = encipher(v,key)
    print enc
    print decipher(enc,key)

And a small sample:

>>> v
[1385482522, 639876499]
>>> tea.decipher(tea.encipher(v,key),key)
[1385482522L, 639876499L]

Solution 2

Since TEA is a block cipher and your v is a very small block, I'd guess there may be block padding differences, or as Wikipedia notes: http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm:

Note that the reference implementation is bound to a specific microprocessor architecture meaning that byte order considerations are important when cyphertext is shared and processed on different systems. The original paper does not specify any details about microprocessor architecture and so anyone implementing a system using TEA would need to make those specifications for themselves.

I didn't inspect either implementation in detail. Your &= statements feel suspicious, too.

Share:
10,923
grzaks
Author by

grzaks

Coder, security researcher, entrepreneur. 15 years of experience in IT related subjects. Author of Udemy video course: Wireshark tutorial for beginners. Author of Automatic Selfie App for Mac OSX: every time you open the macbook lid, a photo is captured using facetime/i-sight camera. For fun and profit.

Updated on July 20, 2022

Comments

  • grzaks
    grzaks almost 2 years

    Anybody knows proper python implementation of TEA (Tiny Encryption Algorithm)? I tried the one I've found here: http://sysadminco.com/code/python-tea/ - but it does not seem to work properly.

    It returns different results than other implementations in C or Java. I guess it's caused by completely different data types in python (or no data types in fact).

    Here's the code and an example:

    def encipher(v, k):
        y=v[0];z=v[1];sum=0;delta=0x9E3779B9;n=32
        w=[0,0]
        while(n>0):
            y += (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3]
            y &= 4294967295L # maxsize of 32-bit integer
            sum += delta
            z += (y << 4 ^ y >> 5) + y ^ sum + k[sum>>11 & 3]
            z &= 4294967295L
            n -= 1
    
        w[0]=y; w[1]=z
        return w
    
    def decipher(v, k):
        y=v[0]
        z=v[1]
        sum=0xC6EF3720
        delta=0x9E3779B9
        n=32
        w=[0,0]
        # sum = delta<<5, in general sum = delta * n
    
        while(n>0):
            z -= (y << 4 ^ y >> 5) + y ^ sum + k[sum>>11 & 3]
            z &= 4294967295L
            sum -= delta
            y -= (z << 4 ^ z >> 5) + z ^ sum + k[sum&3]
            y &= 4294967295L
            n -= 1
    
        w[0]=y; w[1]=z
        return w
    

    Python example:

    >>> import tea
    >>> key = [0xbe168aa1, 0x16c498a3, 0x5e87b018, 0x56de7805]
    >>> v = [0xe15034c8, 0x260fd6d5]
    >>> res = tea.encipher(v, key)
    >>> "%X %X" % (res[0], res[1])
    **'70D16811 F935148F'**
    

    C example:

    #include <unistd.h>
    #include <stdio.h>
    
    void encipher(unsigned long *const v,unsigned long *const w,
       const unsigned long *const k)
    {
       register unsigned long       y=v[0],z=v[1],sum=0,delta=0x9E3779B9,
                                    a=k[0],b=k[1],c=k[2],d=k[3],n=32;
    
       while(n-->0)
          {
          sum += delta;
          y += (z << 4)+a ^ z+sum ^ (z >> 5)+b;
          z += (y << 4)+c ^ y+sum ^ (y >> 5)+d;
          }
    
       w[0]=y; w[1]=z;
    }
    
    int main()
    {
            unsigned long v[] = {0xe15034c8, 0x260fd6d5};
            unsigned long key[] = {0xbe168aa1, 0x16c498a3, 0x5e87b018, 0x56de7805};
    
            unsigned long res[2];
    
            encipher(v, res, key);
    
            printf("%X %X\n", res[0], res[1]);
    
            return 0;
    }
    
    $ ./tea
    **D6942D68 6F87870D**
    

    Please note, that both examples were run with the same input data (v and key), but results were different. I'm pretty sure C implementation is correct - it comes from a site referenced by wikipedia (I couldn't post a link to it because I don't have enough reputation points yet - some antispam thing)

  • grzaks
    grzaks about 14 years
    I can't change the cryptography algorithm in this application. Server-side implementation uses TEA.
  • Seth
    Seth about 14 years
    "There is no point in using unsecure cryptography." Gur fgeratgu bs gur rapelcgvba arrqrq qrcraqf ba jub lbh ner gelvat gb uvqr vg sebz.
  • Luka Rahne
    Luka Rahne about 14 years
    Qute Seth: "the strength of the encryption needed depends on who you are trying to hide it from" Implementing security by default aims at strongest attacker. Otherway you can not claim that your scheme is secure. Just obfuscated.