[Python-au] python number handling - tiny encryption algorithm

Andrew Bennetts andrew-pythonau at puzzling.org
Wed Nov 30 01:48:42 CET 2005


On Wed, Nov 30, 2005 at 10:08:10AM +1100, Kinsley Turner wrote:
[...]
> Which gives me a (broken) python version:
> 
> def  teaDecipher(input,key):
>     y = input[0]
>     z = input[1]
>     n = 32
>     sum = 0xC6EF3720
>     delta=0x9E3779B9 
> 
>     while (n > 0):
>         n -= 1
>         z -= (y << 4 ^ y >> 5) + y ^ sum + key[sum>>11 & 3];
>         sum -= delta;
>         y -= (z << 4 ^ z >> 5) + z ^ sum + key[sum&3];
>       return y,z
> 
> That seems to return hugely-long integers (around 30? digits), whereas I'd 
> expect
> them to max-out at 2^32.

Python's longs are arbitrary length, but you want values truncated to 32-bits.
So you need to do (value & 0xffffffff) anytime value may have overflowed to be
larger than 0xffffffff (the largest 32-bit integer).  Glancing at the code the
obvious places this this could occur are after any left bitshift (<<) or
addition (+) operation.

> Perhaps I'm not packing the input or the key properly.  My inputs are
> just strings which I put into an integer with the ordinal value of each 
> character
> shifted into the correct position to make the C-long.
> 
> Something like:
>     input[0] = ord(encrypted[i])<<24 + ord(encrypted[i+1])<<16 + 
> ord(encrypted[i+2])<<8 + ord(encrypted[i+3])
>     input[1] = ord(encrypted[i+4])<<24 + ord(encrypted[i+5])<<16 + 
> ord(encrypted[i+6])<<8 + ord(encrypted[i+7])
> 
> The key is created as an array of numbers, each the ord() of the key 
> character...

You need to be more careful about operator precedence!  Compare the output of
these two print statments:

    encrypted = 'abcd'
    i = 0
    print ord(encrypted[i])<<24 + ord(encrypted[i+1])<<16 + ord(encrypted[i+2])<<8 + ord(encrypted[i+3])
    print (ord(encrypted[i])<<24) + (ord(encrypted[i+1])<<16) + (ord(encrypted[i+2])<<8) + (ord(encrypted[i+3]))

Something like this would be easier:

    input[0] = struct.unpack('!L', encrypted[i:i+4])[0]
    input[1] = struct.unpack('!L', encrypted[i+4:i+8])[0]

None of this is really Australia-specific, so you'd probably get more help
asking on comp.lang.python / python-list at python.org instead.

-Andrew.




More information about the python-au mailing list