KDELibs4Support

kmd5.cpp
1 /*
2  Copyright (C) 2000-2001 Dawit Alemayehu <[email protected]>
3  Copyright (C) 2001 Rik Hemsley (rikkus) <[email protected]>
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 
61 KMD5::KMD5()
62 {
63  init();
64 }
65 
66 KMD5::KMD5(const char *in, int len)
67 {
68  init();
69  update(in, len);
70 }
71 
72 KMD5::KMD5(const QByteArray &in)
73 {
74  init();
75  update(in);
76 }
77 
78 KMD5::~KMD5()
79 {
80 }
81 
82 void KMD5::update(const QByteArray &in)
83 {
84  update(in.data(), int(in.size()));
85 }
86 
87 void KMD5::update(const char *in, int len)
88 {
89  update(reinterpret_cast<const unsigned char *>(in), len);
90 }
91 
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 
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 
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 
186 bool KMD5::verify(const KMD5::Digest &digest)
187 {
188  finalize();
189  return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest)));
190 }
191 
192 bool KMD5::verify(const QByteArray &hexdigest)
193 {
194  finalize();
195  return (0 == strcmp(hexDigest().data(), hexdigest.data()));
196 }
197 
198 const KMD5::Digest &KMD5::rawDigest()
199 {
200  finalize();
201  return m_digest;
202 }
203 
204 void KMD5::rawDigest(KMD5::Digest &bin)
205 {
206  finalize();
207  memcpy(bin, m_digest, 16);
208 }
209 
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 
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 
234 {
235  finalize();
236  return QByteArray::fromRawData(reinterpret_cast<const char *>(m_digest), 16).toBase64();
237 }
238 
239 void KMD5::init()
240 {
241  d = nullptr;
242  reset();
243 }
244 
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 
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 
351 inline quint32 KMD5::rotate_left(quint32 x, quint32 n)
352 {
353  return (x << n) | (x >> (32 - n));
354 }
355 
356 inline quint32 KMD5::F(quint32 x, quint32 y, quint32 z)
357 {
358  return (x & y) | (~x & z);
359 }
360 
361 inline quint32 KMD5::G(quint32 x, quint32 y, quint32 z)
362 {
363  return (x & z) | (y & ~z);
364 }
365 
366 inline quint32 KMD5::H(quint32 x, quint32 y, quint32 z)
367 {
368  return x ^ y ^ z;
369 }
370 
371 inline quint32 KMD5::I(quint32 x, quint32 y, quint32 z)
372 {
373  return y ^ (x | ~z);
374 }
375 
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 
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 
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 
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 
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.
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 /**************************************************************/
virtual bool atEnd() const const
QByteArray fromRawData(const char *data, int size)
void resize(int size)
bool verify(const KMD5::Digest &digest)
returns true if the calculated digest for the given message matches the given one.
Definition: kmd5.cpp:186
void update(const char *in, int len=-1)
Updates the message to be digested.
Definition: kmd5.cpp:87
qint64 read(char *data, qint64 maxSize)
const Digest & rawDigest()
Definition: kmd5.cpp:198
QByteArray hexDigest()
Returns the value of the calculated message digest in a hexadecimal representation.
Definition: kmd5.cpp:210
void finalize()
finalizes the digest
Definition: kmd5.cpp:150
void transform(const unsigned char buffer[64])
Performs the real update work.
Definition: kmd5.cpp:261
char * data()
void reset()
Calling this function will reset the calculated message digest.
Definition: kmd5.cpp:245
int size() const const
QByteArray base64Digest()
Returns the value of the calculated message digest in a base64-encoded representation.
Definition: kmd5.cpp:233
QByteArray toBase64(QByteArray::Base64Options options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Jul 1 2020 22:56:48 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.