]> jfr.im git - irc/rizon/znc.git/blob - MD5.cpp
Write forceserver and webircpassword to conf
[irc/rizon/znc.git] / MD5.cpp
1 /*
2 * RFC 1321 compliant MD5 implementation
3 *
4 * Copyright (C) 2001-2003 Christophe Devine
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "MD5.h"
22
23 #include <stdio.h>
24 #include <string.h>
25
26 CMD5::CMD5() {
27 *m_szMD5 = '\0';
28 }
29
30 CMD5::CMD5(const string& sText) {
31 MakeHash(sText.c_str(), sText.length());
32 }
33
34 CMD5::CMD5(const char* szText, uint32 nTextLen) {
35 MakeHash(szText, nTextLen);
36 }
37
38 CMD5::~CMD5() {}
39
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); \
45 }
46
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); \
52 }
53
54 void CMD5::md5_starts(md5_context *ctx) const {
55 ctx->total[0] = 0;
56 ctx->total[1] = 0;
57
58 ctx->state[0] = 0x67452301;
59 ctx->state[1] = 0xEFCDAB89;
60 ctx->state[2] = 0x98BADCFE;
61 ctx->state[3] = 0x10325476;
62 }
63
64 void CMD5::md5_process(md5_context *ctx, const uint8 data[64]) const {
65 uint32 X[16], A, B, C, D;
66
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);
83
84 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
85
86 #define P(a,b,c,d,k,s,t) a += F(b,c,d) + X[k] + t; a = S(a,s) + b;
87
88 A = ctx->state[0];
89 B = ctx->state[1];
90 C = ctx->state[2];
91 D = ctx->state[3];
92
93 #define F(x,y,z) (z ^ (x & (y ^ z)))
94
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);
111
112 #undef F
113
114 #define F(x,y,z) (y ^ (z & (x ^ y)))
115
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);
132
133 #undef F
134
135 #define F(x,y,z) (x ^ y ^ z)
136
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);
153
154 #undef F
155
156 #define F(x,y,z) (y ^ (x | ~z))
157
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);
174
175 #undef F
176
177 ctx->state[0] += A;
178 ctx->state[1] += B;
179 ctx->state[2] += C;
180 ctx->state[3] += D;
181 }
182
183 void CMD5::md5_update(md5_context *ctx, const uint8 *input, uint32 length) const {
184 uint32 left, fill;
185
186 if (!length) return;
187
188 left = ctx->total[0] & 0x3F;
189 fill = 64 - left;
190
191 ctx->total[0] += length;
192 ctx->total[0] &= 0xFFFFFFFF;
193
194 if (ctx->total[0] < length)
195 ctx->total[1]++;
196
197 if (left && length >= fill) {
198 memcpy((void *) (ctx->buffer + left),
199 (void *) input, fill);
200 md5_process(ctx, ctx->buffer);
201 length -= fill;
202 input += fill;
203 left = 0;
204 }
205
206 while (length >= 64) {
207 md5_process(ctx, input);
208 length -= 64;
209 input += 64;
210 }
211
212 if (length) {
213 memcpy((void *) (ctx->buffer + left),
214 (void *) input, length);
215 }
216 }
217
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
223 };
224
225 void CMD5::md5_finish(md5_context *ctx, uint8 digest[16]) const {
226 uint32 last, padn;
227 uint32 high, low;
228 uint8 msglen[8];
229
230 high = (ctx->total[0] >> 29)
231 | (ctx->total[1] << 3);
232 low = (ctx->total[0] << 3);
233
234 PUT_UINT32(low, msglen, 0);
235 PUT_UINT32(high, msglen, 4);
236
237 last = ctx->total[0] & 0x3F;
238 padn = (last < 56) ? (56 - last) : (120 - last);
239
240 md5_update(ctx, md5_padding, padn);
241 md5_update(ctx, msglen, 8);
242
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);
247 }
248
249 char* CMD5::MakeHash(const char* szText, uint32 nTextLen) {
250 md5_context ctx;
251 unsigned char md5sum[16];
252
253 md5_starts(&ctx);
254 md5_update(&ctx, (uint8*)szText, nTextLen);
255 md5_finish(&ctx, md5sum);
256
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]);
261
262 return m_szMD5;
263 }