1 /*
2 Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
3 Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License (LGPL)
7 version 2 as published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992. // krazy:exclude=copyright
19 RSA Data Security, Inc. Created 1991. All rights reserved.
20
21 The KMD5 class is based on a C++ implementation of
22 "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by
23 Mordechai T. Abzug, Copyright (c) 1995. This implementation // krazy:exclude=copyright
24 passes the test-suite as defined in RFC 1321.
25
26 The encoding and decoding utilities in KCodecs with the exception of
27 quoted-printable are based on the java implementation in HTTPClient
28 package by Ronald Tschalär Copyright (C) 1996-1999. // krazy:exclude=copyright
29
30 The quoted-printable codec as described in RFC 2045, section 6.7. is by
31 Rik Hemsley (C) 2001.
32 */
33
34 #include "kmd5.h"
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39
40 #include <QDebug>
41 #include <QIODevice>
42 #include <QTextCodec>
43
44 #define KMD5_S11 7
45 #define KMD5_S12 12
46 #define KMD5_S13 17
47 #define KMD5_S14 22
48 #define KMD5_S21 5
49 #define KMD5_S22 9
50 #define KMD5_S23 14
51 #define KMD5_S24 20
52 #define KMD5_S31 4
53 #define KMD5_S32 11
54 #define KMD5_S33 16
55 #define KMD5_S34 23
56 #define KMD5_S41 6
57 #define KMD5_S42 10
58 #define KMD5_S43 15
59 #define KMD5_S44 21
60
KMD5()61 KMD5::KMD5()
62 {
63 init();
64 }
65
KMD5(const char * in,int len)66 KMD5::KMD5(const char *in, int len)
67 {
68 init();
69 update(in, len);
70 }
71
KMD5(const QByteArray & in)72 KMD5::KMD5(const QByteArray &in)
73 {
74 init();
75 update(in);
76 }
77
~KMD5()78 KMD5::~KMD5()
79 {
80 }
81
update(const QByteArray & in)82 void KMD5::update(const QByteArray &in)
83 {
84 update(in.data(), int(in.size()));
85 }
86
update(const char * in,int len)87 void KMD5::update(const char *in, int len)
88 {
89 update(reinterpret_cast<const unsigned char *>(in), len);
90 }
91
update(const unsigned char * in,int len)92 void KMD5::update(const unsigned char *in, int len)
93 {
94 if (len < 0) {
95 len = qstrlen(reinterpret_cast<const char *>(in));
96 }
97
98 if (!len) {
99 return;
100 }
101
102 if (m_finalized) {
103 qWarning() << "KMD5::update called after state was finalized!";
104 return;
105 }
106
107 quint32 in_index;
108 quint32 buffer_index;
109 quint32 buffer_space;
110 quint32 in_length = static_cast<quint32>(len);
111
112 buffer_index = static_cast<quint32>((m_count[0] >> 3) & 0x3F);
113
114 if ((m_count[0] += (in_length << 3)) < (in_length << 3)) {
115 m_count[1]++;
116 }
117
118 m_count[1] += (in_length >> 29);
119 buffer_space = 64 - buffer_index;
120
121 if (in_length >= buffer_space) {
122 memcpy(m_buffer + buffer_index, in, buffer_space);
123 transform(m_buffer);
124
125 for (in_index = buffer_space; in_index + 63 < in_length;
126 in_index += 64) {
127 transform(reinterpret_cast<const unsigned char *>(in + in_index));
128 }
129
130 buffer_index = 0;
131 } else {
132 in_index = 0;
133 }
134
135 memcpy(m_buffer + buffer_index, in + in_index, in_length - in_index);
136 }
137
update(QIODevice & file)138 bool KMD5::update(QIODevice &file)
139 {
140 char buffer[1024];
141 int len;
142
143 while ((len = file.read(buffer, sizeof(buffer))) > 0) {
144 update(buffer, len);
145 }
146
147 return file.atEnd();
148 }
149
finalize()150 void KMD5::finalize()
151 {
152 if (m_finalized) {
153 return;
154 }
155
156 quint8 bits[8];
157 quint32 index, padLen;
158 static const unsigned char PADDING[64] = {
159 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
163 };
164
165 encode(bits, m_count, 8);
166 //memcpy( bits, m_count, 8 );
167
168 // Pad out to 56 mod 64.
169 index = static_cast<quint32>((m_count[0] >> 3) & 0x3f);
170 padLen = (index < 56) ? (56 - index) : (120 - index);
171 update(reinterpret_cast<const char *>(PADDING), padLen);
172
173 // Append length (before padding)
174 update(reinterpret_cast<const char *>(bits), 8);
175
176 // Store state in digest
177 encode(m_digest, m_state, 16);
178 //memcpy( m_digest, m_state, 16 );
179
180 // Fill sensitive information with zero's
181 memset((void *)m_buffer, 0, sizeof(*m_buffer));
182
183 m_finalized = true;
184 }
185
verify(const KMD5::Digest & digest)186 bool KMD5::verify(const KMD5::Digest &digest)
187 {
188 finalize();
189 return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest)));
190 }
191
verify(const QByteArray & hexdigest)192 bool KMD5::verify(const QByteArray &hexdigest)
193 {
194 finalize();
195 return (0 == strcmp(hexDigest().data(), hexdigest.data()));
196 }
197
rawDigest()198 const KMD5::Digest &KMD5::rawDigest()
199 {
200 finalize();
201 return m_digest;
202 }
203
rawDigest(KMD5::Digest & bin)204 void KMD5::rawDigest(KMD5::Digest &bin)
205 {
206 finalize();
207 memcpy(bin, m_digest, 16);
208 }
209
hexDigest()210 QByteArray KMD5::hexDigest()
211 {
212 QByteArray s(32, 0);
213
214 finalize();
215 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
216 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
217 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
218 m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
219
220 return s;
221 }
222
hexDigest(QByteArray & s)223 void KMD5::hexDigest(QByteArray &s)
224 {
225 finalize();
226 s.resize(32);
227 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
228 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
229 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
230 m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
231 }
232
base64Digest()233 QByteArray KMD5::base64Digest()
234 {
235 finalize();
236 return QByteArray::fromRawData(reinterpret_cast<const char *>(m_digest), 16).toBase64();
237 }
238
init()239 void KMD5::init()
240 {
241 d = nullptr;
242 reset();
243 }
244
reset()245 void KMD5::reset()
246 {
247 m_finalized = false;
248
249 m_count[0] = 0;
250 m_count[1] = 0;
251
252 m_state[0] = 0x67452301;
253 m_state[1] = 0xefcdab89;
254 m_state[2] = 0x98badcfe;
255 m_state[3] = 0x10325476;
256
257 memset(m_buffer, 0, sizeof(*m_buffer));
258 memset(m_digest, 0, sizeof(*m_digest));
259 }
260
transform(const unsigned char block[64])261 void KMD5::transform(const unsigned char block[64])
262 {
263
264 quint32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16];
265
266 decode(x, block, 64);
267 //memcpy( x, block, 64 );
268
269 Q_ASSERT(!m_finalized); // not just a user error, since the method is private
270
271 /* Round 1 */
272 FF(a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */
273 FF(d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */
274 FF(c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */
275 FF(b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */
276 FF(a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */
277 FF(d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */
278 FF(c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */
279 FF(b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */
280 FF(a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */
281 FF(d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */
282 FF(c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */
283 FF(b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */
284 FF(a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */
285 FF(d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */
286 FF(c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */
287 FF(b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */
288
289 /* Round 2 */
290 GG(a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */
291 GG(d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */
292 GG(c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */
293 GG(b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */
294 GG(a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */
295 GG(d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */
296 GG(c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */
297 GG(b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */
298 GG(a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */
299 GG(d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */
300 GG(c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */
301 GG(b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */
302 GG(a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */
303 GG(d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */
304 GG(c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */
305 GG(b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */
306
307 /* Round 3 */
308 HH(a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */
309 HH(d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */
310 HH(c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */
311 HH(b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */
312 HH(a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */
313 HH(d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */
314 HH(c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */
315 HH(b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */
316 HH(a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */
317 HH(d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */
318 HH(c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */
319 HH(b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */
320 HH(a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */
321 HH(d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */
322 HH(c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */
323 HH(b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */
324
325 /* Round 4 */
326 II(a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */
327 II(d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */
328 II(c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */
329 II(b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */
330 II(a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */
331 II(d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */
332 II(c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */
333 II(b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */
334 II(a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */
335 II(d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */
336 II(c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */
337 II(b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */
338 II(a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */
339 II(d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */
340 II(c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */
341 II(b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */
342
343 m_state[0] += a;
344 m_state[1] += b;
345 m_state[2] += c;
346 m_state[3] += d;
347
348 memset(static_cast<void *>(x), 0, sizeof(x));
349 }
350
rotate_left(quint32 x,quint32 n)351 inline quint32 KMD5::rotate_left(quint32 x, quint32 n)
352 {
353 return (x << n) | (x >> (32 - n));
354 }
355
F(quint32 x,quint32 y,quint32 z)356 inline quint32 KMD5::F(quint32 x, quint32 y, quint32 z)
357 {
358 return (x & y) | (~x & z);
359 }
360
G(quint32 x,quint32 y,quint32 z)361 inline quint32 KMD5::G(quint32 x, quint32 y, quint32 z)
362 {
363 return (x & z) | (y & ~z);
364 }
365
H(quint32 x,quint32 y,quint32 z)366 inline quint32 KMD5::H(quint32 x, quint32 y, quint32 z)
367 {
368 return x ^ y ^ z;
369 }
370
I(quint32 x,quint32 y,quint32 z)371 inline quint32 KMD5::I(quint32 x, quint32 y, quint32 z)
372 {
373 return y ^ (x | ~z);
374 }
375
FF(quint32 & a,quint32 b,quint32 c,quint32 d,quint32 x,quint32 s,quint32 ac)376 void KMD5::FF(quint32 &a, quint32 b, quint32 c, quint32 d,
377 quint32 x, quint32 s, quint32 ac)
378 {
379 a += F(b, c, d) + x + ac;
380 a = rotate_left(a, s) + b;
381 }
382
GG(quint32 & a,quint32 b,quint32 c,quint32 d,quint32 x,quint32 s,quint32 ac)383 void KMD5::GG(quint32 &a, quint32 b, quint32 c, quint32 d,
384 quint32 x, quint32 s, quint32 ac)
385 {
386 a += G(b, c, d) + x + ac;
387 a = rotate_left(a, s) + b;
388 }
389
HH(quint32 & a,quint32 b,quint32 c,quint32 d,quint32 x,quint32 s,quint32 ac)390 void KMD5::HH(quint32 &a, quint32 b, quint32 c, quint32 d,
391 quint32 x, quint32 s, quint32 ac)
392 {
393 a += H(b, c, d) + x + ac;
394 a = rotate_left(a, s) + b;
395 }
396
II(quint32 & a,quint32 b,quint32 c,quint32 d,quint32 x,quint32 s,quint32 ac)397 void KMD5::II(quint32 &a, quint32 b, quint32 c, quint32 d,
398 quint32 x, quint32 s, quint32 ac)
399 {
400 a += I(b, c, d) + x + ac;
401 a = rotate_left(a, s) + b;
402 }
403
encode(unsigned char * output,quint32 * in,quint32 len)404 void KMD5::encode(unsigned char *output, quint32 *in, quint32 len)
405 {
406 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
407 memcpy(output, in, len);
408 #else
409 quint32 i, j;
410 for (i = 0, j = 0; j < len; i++, j += 4) {
411 output[j] = static_cast<quint8>((in[i] & 0xff));
412 output[j + 1] = static_cast<quint8>(((in[i] >> 8) & 0xff));
413 output[j + 2] = static_cast<quint8>(((in[i] >> 16) & 0xff));
414 output[j + 3] = static_cast<quint8>(((in[i] >> 24) & 0xff));
415 }
416 #endif
417 }
418
419 // Decodes in (quint8) into output (quint32). Assumes len is a
420 // multiple of 4.
decode(quint32 * output,const unsigned char * in,quint32 len)421 void KMD5::decode(quint32 *output, const unsigned char *in, quint32 len)
422 {
423 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
424 memcpy(output, in, len);
425
426 #else
427 quint32 i, j;
428 for (i = 0, j = 0; j < len; i++, j += 4)
429 output[i] = static_cast<quint32>(in[j]) |
430 (static_cast<quint32>(in[j + 1]) << 8) |
431 (static_cast<quint32>(in[j + 2]) << 16) |
432 (static_cast<quint32>(in[j + 3]) << 24);
433 #endif
434 }
435
436 /**************************************************************/
437