]>
jfr.im git - irc/rizon/znc.git/blob - MD5.cpp
2 * RFC 1321 compliant MD5 implementation
4 * Copyright (C) 2001-2003 Christophe Devine
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 CMD5::CMD5(const string
& sText
) {
31 MakeHash(sText
.c_str(), sText
.length());
34 CMD5::CMD5(const char* szText
, uint32 nTextLen
) {
35 MakeHash(szText
, nTextLen
);
40 #define GET_UINT32(n,b,i) { \
41 (n) = ((uint32) (b)[(i) ] ) \
42 | ((uint32) (b)[(i) + 1] << 8) \
43 | ((uint32) (b)[(i) + 2] << 16) \
44 | ((uint32) (b)[(i) + 3] << 24); \
47 #define PUT_UINT32(n,b,i) { \
48 (b)[(i) ] = (uint8) ((n) ); \
49 (b)[(i) + 1] = (uint8) ((n) >> 8); \
50 (b)[(i) + 2] = (uint8) ((n) >> 16); \
51 (b)[(i) + 3] = (uint8) ((n) >> 24); \
54 void CMD5::md5_starts(md5_context
*ctx
) const {
58 ctx
->state
[0] = 0x67452301;
59 ctx
->state
[1] = 0xEFCDAB89;
60 ctx
->state
[2] = 0x98BADCFE;
61 ctx
->state
[3] = 0x10325476;
64 void CMD5::md5_process(md5_context
*ctx
, const uint8 data
[64]) const {
65 uint32 X
[16], A
, B
, C
, D
;
67 GET_UINT32(X
[0], data
, 0);
68 GET_UINT32(X
[1], data
, 4);
69 GET_UINT32(X
[2], data
, 8);
70 GET_UINT32(X
[3], data
, 12);
71 GET_UINT32(X
[4], data
, 16);
72 GET_UINT32(X
[5], data
, 20);
73 GET_UINT32(X
[6], data
, 24);
74 GET_UINT32(X
[7], data
, 28);
75 GET_UINT32(X
[8], data
, 32);
76 GET_UINT32(X
[9], data
, 36);
77 GET_UINT32(X
[10], data
, 40);
78 GET_UINT32(X
[11], data
, 44);
79 GET_UINT32(X
[12], data
, 48);
80 GET_UINT32(X
[13], data
, 52);
81 GET_UINT32(X
[14], data
, 56);
82 GET_UINT32(X
[15], data
, 60);
84 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
86 #define P(a,b,c,d,k,s,t) a += F(b,c,d) + X[k] + t; a = S(a,s) + b;
93 #define F(x,y,z) (z ^ (x & (y ^ z)))
95 P(A
, B
, C
, D
, 0, 7, 0xD76AA478);
96 P(D
, A
, B
, C
, 1, 12, 0xE8C7B756);
97 P(C
, D
, A
, B
, 2, 17, 0x242070DB);
98 P(B
, C
, D
, A
, 3, 22, 0xC1BDCEEE);
99 P(A
, B
, C
, D
, 4, 7, 0xF57C0FAF);
100 P(D
, A
, B
, C
, 5, 12, 0x4787C62A);
101 P(C
, D
, A
, B
, 6, 17, 0xA8304613);
102 P(B
, C
, D
, A
, 7, 22, 0xFD469501);
103 P(A
, B
, C
, D
, 8, 7, 0x698098D8);
104 P(D
, A
, B
, C
, 9, 12, 0x8B44F7AF);
105 P(C
, D
, A
, B
, 10, 17, 0xFFFF5BB1);
106 P(B
, C
, D
, A
, 11, 22, 0x895CD7BE);
107 P(A
, B
, C
, D
, 12, 7, 0x6B901122);
108 P(D
, A
, B
, C
, 13, 12, 0xFD987193);
109 P(C
, D
, A
, B
, 14, 17, 0xA679438E);
110 P(B
, C
, D
, A
, 15, 22, 0x49B40821);
114 #define F(x,y,z) (y ^ (z & (x ^ y)))
116 P(A
, B
, C
, D
, 1, 5, 0xF61E2562);
117 P(D
, A
, B
, C
, 6, 9, 0xC040B340);
118 P(C
, D
, A
, B
, 11, 14, 0x265E5A51);
119 P(B
, C
, D
, A
, 0, 20, 0xE9B6C7AA);
120 P(A
, B
, C
, D
, 5, 5, 0xD62F105D);
121 P(D
, A
, B
, C
, 10, 9, 0x02441453);
122 P(C
, D
, A
, B
, 15, 14, 0xD8A1E681);
123 P(B
, C
, D
, A
, 4, 20, 0xE7D3FBC8);
124 P(A
, B
, C
, D
, 9, 5, 0x21E1CDE6);
125 P(D
, A
, B
, C
, 14, 9, 0xC33707D6);
126 P(C
, D
, A
, B
, 3, 14, 0xF4D50D87);
127 P(B
, C
, D
, A
, 8, 20, 0x455A14ED);
128 P(A
, B
, C
, D
, 13, 5, 0xA9E3E905);
129 P(D
, A
, B
, C
, 2, 9, 0xFCEFA3F8);
130 P(C
, D
, A
, B
, 7, 14, 0x676F02D9);
131 P(B
, C
, D
, A
, 12, 20, 0x8D2A4C8A);
135 #define F(x,y,z) (x ^ y ^ z)
137 P(A
, B
, C
, D
, 5, 4, 0xFFFA3942);
138 P(D
, A
, B
, C
, 8, 11, 0x8771F681);
139 P(C
, D
, A
, B
, 11, 16, 0x6D9D6122);
140 P(B
, C
, D
, A
, 14, 23, 0xFDE5380C);
141 P(A
, B
, C
, D
, 1, 4, 0xA4BEEA44);
142 P(D
, A
, B
, C
, 4, 11, 0x4BDECFA9);
143 P(C
, D
, A
, B
, 7, 16, 0xF6BB4B60);
144 P(B
, C
, D
, A
, 10, 23, 0xBEBFBC70);
145 P(A
, B
, C
, D
, 13, 4, 0x289B7EC6);
146 P(D
, A
, B
, C
, 0, 11, 0xEAA127FA);
147 P(C
, D
, A
, B
, 3, 16, 0xD4EF3085);
148 P(B
, C
, D
, A
, 6, 23, 0x04881D05);
149 P(A
, B
, C
, D
, 9, 4, 0xD9D4D039);
150 P(D
, A
, B
, C
, 12, 11, 0xE6DB99E5);
151 P(C
, D
, A
, B
, 15, 16, 0x1FA27CF8);
152 P(B
, C
, D
, A
, 2, 23, 0xC4AC5665);
156 #define F(x,y,z) (y ^ (x | ~z))
158 P(A
, B
, C
, D
, 0, 6, 0xF4292244);
159 P(D
, A
, B
, C
, 7, 10, 0x432AFF97);
160 P(C
, D
, A
, B
, 14, 15, 0xAB9423A7);
161 P(B
, C
, D
, A
, 5, 21, 0xFC93A039);
162 P(A
, B
, C
, D
, 12, 6, 0x655B59C3);
163 P(D
, A
, B
, C
, 3, 10, 0x8F0CCC92);
164 P(C
, D
, A
, B
, 10, 15, 0xFFEFF47D);
165 P(B
, C
, D
, A
, 1, 21, 0x85845DD1);
166 P(A
, B
, C
, D
, 8, 6, 0x6FA87E4F);
167 P(D
, A
, B
, C
, 15, 10, 0xFE2CE6E0);
168 P(C
, D
, A
, B
, 6, 15, 0xA3014314);
169 P(B
, C
, D
, A
, 13, 21, 0x4E0811A1);
170 P(A
, B
, C
, D
, 4, 6, 0xF7537E82);
171 P(D
, A
, B
, C
, 11, 10, 0xBD3AF235);
172 P(C
, D
, A
, B
, 2, 15, 0x2AD7D2BB);
173 P(B
, C
, D
, A
, 9, 21, 0xEB86D391);
183 void CMD5::md5_update(md5_context
*ctx
, const uint8
*input
, uint32 length
) const {
188 left
= ctx
->total
[0] & 0x3F;
191 ctx
->total
[0] += length
;
192 ctx
->total
[0] &= 0xFFFFFFFF;
194 if (ctx
->total
[0] < length
)
197 if (left
&& length
>= fill
) {
198 memcpy((void *) (ctx
->buffer
+ left
),
199 (void *) input
, fill
);
200 md5_process(ctx
, ctx
->buffer
);
206 while (length
>= 64) {
207 md5_process(ctx
, input
);
213 memcpy((void *) (ctx
->buffer
+ left
),
214 (void *) input
, length
);
218 static const uint8 md5_padding
[64] = {
219 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
220 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
225 void CMD5::md5_finish(md5_context
*ctx
, uint8 digest
[16]) const {
230 high
= (ctx
->total
[0] >> 29)
231 | (ctx
->total
[1] << 3);
232 low
= (ctx
->total
[0] << 3);
234 PUT_UINT32(low
, msglen
, 0);
235 PUT_UINT32(high
, msglen
, 4);
237 last
= ctx
->total
[0] & 0x3F;
238 padn
= (last
< 56) ? (56 - last
) : (120 - last
);
240 md5_update(ctx
, md5_padding
, padn
);
241 md5_update(ctx
, msglen
, 8);
243 PUT_UINT32(ctx
->state
[0], digest
, 0);
244 PUT_UINT32(ctx
->state
[1], digest
, 4);
245 PUT_UINT32(ctx
->state
[2], digest
, 8);
246 PUT_UINT32(ctx
->state
[3], digest
, 12);
249 char* CMD5::MakeHash(const char* szText
, uint32 nTextLen
) {
251 unsigned char md5sum
[16];
254 md5_update(&ctx
, (uint8
*)szText
, nTextLen
);
255 md5_finish(&ctx
, md5sum
);
257 sprintf(m_szMD5
, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
258 md5sum
[0], md5sum
[1], md5sum
[2], md5sum
[3], md5sum
[4], md5sum
[5],
259 md5sum
[6], md5sum
[7], md5sum
[8], md5sum
[9], md5sum
[10], md5sum
[11],
260 md5sum
[12], md5sum
[13], md5sum
[14], md5sum
[15]);