I really give up

QnickQm at alum.mit.edu QnickQm at alum.mit.edu
Wed Oct 2 11:56:17 EDT 2002


In article <anf1bj$vu$1 at news.tpi.pl>, piter wrote:
> Hey guys,
> 
> I really give up! How to convert the following C function into python?
> 
> //-----------------------------------------
> unsigned int
> make_hash(char *password, unsigned int seed)
> {
>     unsigned int x, y, z;
> 
>     y = seed;
> 
>     for (x = 0; *password; password++) {
>         x = (x & 0xffffff00) | *password;
>         y ^= x;
>         y += x;
>         x <<= 8;
>         y ^= x;
>         x <<= 8;
>         y -= x;
>         x <<= 8;
>         y ^= x;
> 
>         z = y & 0x1f;
>         y = (y << z) | (y >> (32 - z));
>     }
> 
>     return y;
> }
> 
> //-----------------------------------------
> 
> The obvious solution:
 [...]
> produces odd result due to python's signed arithmetic.

One solution: use the low-order bytes of Python's long integers.

def make_hash(password, seed):
    y = long(seed)
    x = 0L
    for ch in password:
        x = (x & 0xffffff00L) | ord(ch)
        y ^= x
        y += x
        x <<= 8
        y ^= x
        x <<= 8
        y -= x
        x <<= 8
        y ^= x
        z = int(y & 0x1f)
        y &= 0xffffffffL
        y = ((y << z) | ((y >> (32- z))))

    return y & 0xffffffffL

Note however that this hashing algorithm is *not* secure.  A decent desktop
takes less than 4 minutes to try 2**32 passwords with a given seed.  Thus,
assuming that the hashing algorithm works, I can should be able to find 
a password that hashes to any desired hash value for a given seed in that
amount of time.  You may as well store the passwords in plaintext.

Instead, may I suggest the sha module?  

Avoiding-roll-your-own-crypto-like-the-plague-ly y'rs,

-- 
 Nick Mathewson    <Q nick Q m at alum dot mit dot edu>
                      Remove Q's to respond.  No spam.



More information about the Python-list mailing list