2 * $Id: md5.c,v 1.2 2008/03/24 20:59:12 mascarenhas Exp $
4 * @author Marcela Ozorio Suarez, Roberto I.
14 #define MASK 0xFFFFFFFF
15 #if __STDC_VERSION__ >= 199901L
17 typedef uint32_t WORD32
;
19 typedef unsigned int WORD32
;
25 * @param message: aribtary string.
26 * @param len: message length.
27 * @param output: buffer to receive the hash value. Its size must be
28 * (at least) HASHSIZE.
30 void md5 (const char *message
, long len
, char *output
);
35 ** Realiza a rotacao no sentido horario dos bits da variavel 'D' do tipo WORD32.
36 ** Os bits sao deslocados de 'num' posicoes
38 #define rotate(D, num) (D<<num) | (D>>(WORD-num))
40 /*Macros que definem operacoes relizadas pelo algoritmo md5 */
41 #define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
42 #define G(x, y, z) (((x) & (z)) | ((y) & (~(z))))
43 #define H(x, y, z) ((x) ^ (y) ^ (z))
44 #define I(x, y, z) ((y) ^ ((x) | (~(z))))
47 /*vetor de numeros utilizados pelo algoritmo md5 para embaralhar bits */
48 static const WORD32 T
[64]={
49 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
50 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
51 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
52 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
53 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
54 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
55 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
56 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
57 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
58 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
59 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
60 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
61 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
62 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
63 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
64 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
68 static void word32tobytes (const WORD32
*input
, char *output
) {
72 output
[j
++] = (char)(v
& 0xff); v
>>= 8;
73 output
[j
++] = (char)(v
& 0xff); v
>>= 8;
74 output
[j
++] = (char)(v
& 0xff); v
>>= 8;
75 output
[j
++] = (char)(v
& 0xff);
80 static void inic_digest(WORD32
*d
) {
88 /*funcao que implemeta os quatro passos principais do algoritmo MD5 */
89 static void digest(const WORD32
*m
, WORD32
*d
) {
92 for (j
=0; j
<4*4; j
+=4) {
93 d
[0] = d
[0]+ F(d
[1], d
[2], d
[3])+ m
[j
] + T
[j
]; d
[0]=rotate(d
[0], 7);
95 d
[3] = d
[3]+ F(d
[0], d
[1], d
[2])+ m
[(j
)+1] + T
[j
+1]; d
[3]=rotate(d
[3], 12);
97 d
[2] = d
[2]+ F(d
[3], d
[0], d
[1])+ m
[(j
)+2] + T
[j
+2]; d
[2]=rotate(d
[2], 17);
99 d
[1] = d
[1]+ F(d
[2], d
[3], d
[0])+ m
[(j
)+3] + T
[j
+3]; d
[1]=rotate(d
[1], 22);
103 for (j
=0; j
<4*4; j
+=4) {
104 d
[0] = d
[0]+ G(d
[1], d
[2], d
[3])+ m
[(5*j
+1)&0x0f] + T
[(j
-1)+17];
105 d
[0] = rotate(d
[0],5);
107 d
[3] = d
[3]+ G(d
[0], d
[1], d
[2])+ m
[((5*(j
+1)+1)&0x0f)] + T
[(j
+0)+17];
108 d
[3] = rotate(d
[3], 9);
110 d
[2] = d
[2]+ G(d
[3], d
[0], d
[1])+ m
[((5*(j
+2)+1)&0x0f)] + T
[(j
+1)+17];
111 d
[2] = rotate(d
[2], 14);
113 d
[1] = d
[1]+ G(d
[2], d
[3], d
[0])+ m
[((5*(j
+3)+1)&0x0f)] + T
[(j
+2)+17];
114 d
[1] = rotate(d
[1], 20);
118 for (j
=0; j
<4*4; j
+=4) {
119 d
[0] = d
[0]+ H(d
[1], d
[2], d
[3])+ m
[(3*j
+5)&0x0f] + T
[(j
-1)+33];
120 d
[0] = rotate(d
[0], 4);
122 d
[3] = d
[3]+ H(d
[0], d
[1], d
[2])+ m
[(3*(j
+1)+5)&0x0f] + T
[(j
+0)+33];
123 d
[3] = rotate(d
[3], 11);
125 d
[2] = d
[2]+ H(d
[3], d
[0], d
[1])+ m
[(3*(j
+2)+5)&0x0f] + T
[(j
+1)+33];
126 d
[2] = rotate(d
[2], 16);
128 d
[1] = d
[1]+ H(d
[2], d
[3], d
[0])+ m
[(3*(j
+3)+5)&0x0f] + T
[(j
+2)+33];
129 d
[1] = rotate(d
[1], 23);
133 for (j
=0; j
<4*4; j
+=4) {
134 d
[0] = d
[0]+ I(d
[1], d
[2], d
[3])+ m
[(7*j
)&0x0f] + T
[(j
-1)+49];
135 d
[0] = rotate(d
[0], 6);
137 d
[3] = d
[3]+ I(d
[0], d
[1], d
[2])+ m
[(7*(j
+1))&0x0f] + T
[(j
+0)+49];
138 d
[3] = rotate(d
[3], 10);
140 d
[2] = d
[2]+ I(d
[3], d
[0], d
[1])+ m
[(7*(j
+2))&0x0f] + T
[(j
+1)+49];
141 d
[2] = rotate(d
[2], 15);
143 d
[1] = d
[1]+ I(d
[2], d
[3], d
[0])+ m
[(7*(j
+3))&0x0f] + T
[(j
+2)+49];
144 d
[1] = rotate(d
[1], 21);
150 static void bytestoword32 (WORD32
*x
, const char *pt
) {
152 for (i
=0; i
<16; i
++) {
154 x
[i
] = (((WORD32
)(unsigned char)pt
[j
+3] << 8 |
155 (WORD32
)(unsigned char)pt
[j
+2]) << 8 |
156 (WORD32
)(unsigned char)pt
[j
+1]) << 8 |
157 (WORD32
)(unsigned char)pt
[j
];
163 static void put_length(WORD32
*x
, long len
) {
165 x
[14] = (WORD32
)((len
<<3) & MASK
);
166 x
[15] = (WORD32
)(len
>>(32-3) & 0x7);
172 * 0 - normal message (full 64 bytes)
173 * 1 - enough room for 0x80, but not for message length (two 4-byte words)
174 * 2 - enough room for 0x80 plus message length (at least 9 bytes free)
176 static int converte (WORD32
*x
, const char *pt
, int num
, int old_status
) {
180 memcpy(buff
, pt
, num
); /* to avoid changing original string */
181 memset(buff
+num
, 0, 64-num
);
187 bytestoword32(x
, pt
);
195 void md5 (const char *message
, long len
, char *output
) {
200 while (status
!= 2) {
203 int numbytes
= (len
-i
>= 64) ? 64 : len
-i
;
204 /*salva os valores do vetor digest*/
205 d_old
[0]=d
[0]; d_old
[1]=d
[1]; d_old
[2]=d
[2]; d_old
[3]=d
[3];
206 status
= converte(wbuff
, message
+i
, numbytes
, status
);
207 if (status
== 2) put_length(wbuff
, len
);
209 d
[0]+=d_old
[0]; d
[1]+=d_old
[1]; d
[2]+=d_old
[2]; d
[3]+=d_old
[3];
212 word32tobytes(d
, output
);