#! /usr/bin/env python ############################################################################# ## ## ## md5.py -- calculate the md5 hash of stdin ## ## ## ## ## ## Copyright (C) 2004 Philippe Biondi ## ## ## ## This program is free software; you can redistribute it and/or modify it ## ## under the terms of the GNU General Public License as published by the ## ## Free Software Foundation; either version 2, or (at your option) any ## ## later version. ## ## ## ## This program is distributed in the hope that it will be useful, but ## ## WITHOUT ANY WARRANTY; without even the implied warranty of ## ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## ## General Public License for more details. ## ## ## ############################################################################# # $Id: md5.py,v 1.2 2004/07/25 11:30:03 pbi Exp pbi $ import sys,math,struct S=[[7,12,17,22], [5,9,14,20], [4,11,16,23], [6,10,15,21]] O=[0,1,5,0] M=[1,5,3,7] T = map(lambda i: long(4294967296.0*abs(math.sin(i))), range(1,65)) A,B,C,D=struct.unpack("> (32-s)) return (a+b) & (2**32-1) FF = lambda *args: K(F,*args) GG = lambda *args: K(G,*args) HH = lambda *args: K(H,*args) II = lambda *args: K(I,*args) Func=[FF,GG,HH,II] finished=0 l=0 while 1: if finished: chunk = chunk[64:] if len(chunk) < 64: break else: chunk = sys.stdin.read(64) l += len(chunk) if len(chunk) < 64: # Padding is always added : # \x80+some \x00+bitlen (on 8 bytes, little endian) # so that the input length is a multiple of 64 bytes. chunk += "\x80" chunk += "\x00"*( (64+56-(l+1))%64 ) chunk += struct.pack(">32)&(2**32-1)) finished = 1 L=[A,B,C,D] for round in range(4): for j in range(4): for k in range(4): ofs= ((j*4+k)*M[round]+O[round]) % 16 L[-k]=Func[round](L[-k],L[1-k],L[2-k],L[3-k], struct.unpack(">8)&0xff, (x>>16)&0xff,(x>>24)&0xff) print pr(A)+pr(B)+pr(C)+pr(D)