from struct import pack, unpack # pour gérer le little-endian
from math import sin
s = [ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 ]
K = [0]*64
for i in range(64): K[i] = int(2**32 * abs(sin(i + 1.)))
print ([hex(k) for k in K])
#Padding. On doit arriver à un multiple de 512 bits
from codecs import *
def pad(x):
m = len (x)*8
d = (m%512) - 448 # On concatène un bit 1 suivi de d-1 bits 0
if d<0: d = -d # pour arriver à un nomnbre congru à 448 modulo 512
else: d = 512 - d
# p = decode('%X' % int('1'+'0'*(d-1),2),'hex') # pour tester
# ou encore a = 1<<(d-1)
# p = a.to_bytes((d//8),'big')
p = decode('%X' % (1<<(d-1)),'hex')
y = x+p
n = pack('<Q',(m % 2**64) ) # les 64 derniers codent m en little-endian
return y+n
def split(x): # On découpe x en blocs de 64 octets = 512 bits
assert len(x) % 64 == 0
return [x[i*64:(i+1)*64] for i in range(len(x)//64)]
def leftrotate(x,c): # La fonction définie dans la spécification; calculs modulo 2**32
x &= 0xffffffff
return (x <<c ) | (x >>(32-c)) & 0xffffffff
def md5sum(x):
a0 = 0x67452301 #A
b0 = 0xefcdab89 #B
c0 = 0x98badcfe #C
d0 = 0x10325476 #D
y = pad(x)
chunks = split(y)
for chunk in chunks:
M = unpack('<16I',chunk) # On décode en 16 "unsigned int", little-endian
A,B,C,D = a0,b0,c0,d0
for i in range(64):
if i in range(16):
F = (B&C) | ((~B)&D)
g = i
elif i in range(16,32):
F = (D&B) | ((~D)&C)
g = (5*i+1) % 16
elif i in range(32,48):
F = B^C^D
g = (3*i+5) % 16
else:
F = C^(B|(~D))
g = (7*i) % 16
dTemp = D
D = C
C = B
B = (B + leftrotate((A + F + K[i] + M[g]), s[i])) & 0xffffffff
A = dTemp
a0 = (a0+A) & 0xffffffff
b0 = (b0+B) & 0xffffffff
c0 = (c0+C) & 0xffffffff
d0 = (d0+D) & 0xffffffff
digest = (a0,b0,c0,d0)
return encode(pack('<4I',*digest),'hex')
md5sum(b'')
from hashlib import md5
md5(b'').hexdigest()
print (md5sum(b'abracadabra'*666))
print (md5(b'abracadabra'*666).hexdigest())
pad(b'\x00'*8)
bin(ord('@'))
pad(b'AAAAAAAA')