File indexing completed on 2023-09-24 04:04:53
0001 /* 0002 Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org> 0003 Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org> 0004 0005 This program is free software; you can redistribute it and/or modify 0006 it under the terms of the GNU Lesser General Public License (LGPL) 0007 version 2 as published by the Free Software Foundation. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 GNU Lesser General Public License for more details. 0013 0014 You should have received a copy of the GNU Lesser General Public 0015 License along with this program; if not, write to the Free Software 0016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0017 0018 RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992. // krazy:exclude=copyright 0019 RSA Data Security, Inc. Created 1991. All rights reserved. 0020 0021 The KMD5 class is based on a C++ implementation of 0022 "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by 0023 Mordechai T. Abzug, Copyright (c) 1995. This implementation // krazy:exclude=copyright 0024 passes the test-suite as defined in RFC 1321. 0025 0026 The encoding and decoding utilities in KCodecs with the exception of 0027 quoted-printable are based on the java implementation in HTTPClient 0028 package by Ronald Tschalär Copyright (C) 1996-1999. // krazy:exclude=copyright 0029 0030 The quoted-printable codec as described in RFC 2045, section 6.7. is by 0031 Rik Hemsley (C) 2001. 0032 */ 0033 0034 #include "kmd5.h" 0035 0036 #include <stdio.h> 0037 #include <string.h> 0038 #include <stdlib.h> 0039 0040 #include <QDebug> 0041 #include <QIODevice> 0042 #include <QTextCodec> 0043 0044 #define KMD5_S11 7 0045 #define KMD5_S12 12 0046 #define KMD5_S13 17 0047 #define KMD5_S14 22 0048 #define KMD5_S21 5 0049 #define KMD5_S22 9 0050 #define KMD5_S23 14 0051 #define KMD5_S24 20 0052 #define KMD5_S31 4 0053 #define KMD5_S32 11 0054 #define KMD5_S33 16 0055 #define KMD5_S34 23 0056 #define KMD5_S41 6 0057 #define KMD5_S42 10 0058 #define KMD5_S43 15 0059 #define KMD5_S44 21 0060 0061 KMD5::KMD5() 0062 { 0063 init(); 0064 } 0065 0066 KMD5::KMD5(const char *in, int len) 0067 { 0068 init(); 0069 update(in, len); 0070 } 0071 0072 KMD5::KMD5(const QByteArray &in) 0073 { 0074 init(); 0075 update(in); 0076 } 0077 0078 KMD5::~KMD5() 0079 { 0080 } 0081 0082 void KMD5::update(const QByteArray &in) 0083 { 0084 update(in.data(), int(in.size())); 0085 } 0086 0087 void KMD5::update(const char *in, int len) 0088 { 0089 update(reinterpret_cast<const unsigned char *>(in), len); 0090 } 0091 0092 void KMD5::update(const unsigned char *in, int len) 0093 { 0094 if (len < 0) { 0095 len = qstrlen(reinterpret_cast<const char *>(in)); 0096 } 0097 0098 if (!len) { 0099 return; 0100 } 0101 0102 if (m_finalized) { 0103 qWarning() << "KMD5::update called after state was finalized!"; 0104 return; 0105 } 0106 0107 quint32 in_index; 0108 quint32 buffer_index; 0109 quint32 buffer_space; 0110 quint32 in_length = static_cast<quint32>(len); 0111 0112 buffer_index = static_cast<quint32>((m_count[0] >> 3) & 0x3F); 0113 0114 if ((m_count[0] += (in_length << 3)) < (in_length << 3)) { 0115 m_count[1]++; 0116 } 0117 0118 m_count[1] += (in_length >> 29); 0119 buffer_space = 64 - buffer_index; 0120 0121 if (in_length >= buffer_space) { 0122 memcpy(m_buffer + buffer_index, in, buffer_space); 0123 transform(m_buffer); 0124 0125 for (in_index = buffer_space; in_index + 63 < in_length; 0126 in_index += 64) { 0127 transform(reinterpret_cast<const unsigned char *>(in + in_index)); 0128 } 0129 0130 buffer_index = 0; 0131 } else { 0132 in_index = 0; 0133 } 0134 0135 memcpy(m_buffer + buffer_index, in + in_index, in_length - in_index); 0136 } 0137 0138 bool KMD5::update(QIODevice &file) 0139 { 0140 char buffer[1024]; 0141 int len; 0142 0143 while ((len = file.read(buffer, sizeof(buffer))) > 0) { 0144 update(buffer, len); 0145 } 0146 0147 return file.atEnd(); 0148 } 0149 0150 void KMD5::finalize() 0151 { 0152 if (m_finalized) { 0153 return; 0154 } 0155 0156 quint8 bits[8]; 0157 quint32 index, padLen; 0158 static const unsigned char PADDING[64] = { 0159 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0161 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0162 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0163 }; 0164 0165 encode(bits, m_count, 8); 0166 //memcpy( bits, m_count, 8 ); 0167 0168 // Pad out to 56 mod 64. 0169 index = static_cast<quint32>((m_count[0] >> 3) & 0x3f); 0170 padLen = (index < 56) ? (56 - index) : (120 - index); 0171 update(reinterpret_cast<const char *>(PADDING), padLen); 0172 0173 // Append length (before padding) 0174 update(reinterpret_cast<const char *>(bits), 8); 0175 0176 // Store state in digest 0177 encode(m_digest, m_state, 16); 0178 //memcpy( m_digest, m_state, 16 ); 0179 0180 // Fill sensitive information with zero's 0181 memset((void *)m_buffer, 0, sizeof(*m_buffer)); 0182 0183 m_finalized = true; 0184 } 0185 0186 bool KMD5::verify(const KMD5::Digest &digest) 0187 { 0188 finalize(); 0189 return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest))); 0190 } 0191 0192 bool KMD5::verify(const QByteArray &hexdigest) 0193 { 0194 finalize(); 0195 return (0 == strcmp(hexDigest().data(), hexdigest.data())); 0196 } 0197 0198 const KMD5::Digest &KMD5::rawDigest() 0199 { 0200 finalize(); 0201 return m_digest; 0202 } 0203 0204 void KMD5::rawDigest(KMD5::Digest &bin) 0205 { 0206 finalize(); 0207 memcpy(bin, m_digest, 16); 0208 } 0209 0210 QByteArray KMD5::hexDigest() 0211 { 0212 QByteArray s(32, 0); 0213 0214 finalize(); 0215 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 0216 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 0217 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 0218 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 0219 0220 return s; 0221 } 0222 0223 void KMD5::hexDigest(QByteArray &s) 0224 { 0225 finalize(); 0226 s.resize(32); 0227 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 0228 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5], 0229 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11], 0230 m_digest[12], m_digest[13], m_digest[14], m_digest[15]); 0231 } 0232 0233 QByteArray KMD5::base64Digest() 0234 { 0235 finalize(); 0236 return QByteArray::fromRawData(reinterpret_cast<const char *>(m_digest), 16).toBase64(); 0237 } 0238 0239 void KMD5::init() 0240 { 0241 d = nullptr; 0242 reset(); 0243 } 0244 0245 void KMD5::reset() 0246 { 0247 m_finalized = false; 0248 0249 m_count[0] = 0; 0250 m_count[1] = 0; 0251 0252 m_state[0] = 0x67452301; 0253 m_state[1] = 0xefcdab89; 0254 m_state[2] = 0x98badcfe; 0255 m_state[3] = 0x10325476; 0256 0257 memset(m_buffer, 0, sizeof(*m_buffer)); 0258 memset(m_digest, 0, sizeof(*m_digest)); 0259 } 0260 0261 void KMD5::transform(const unsigned char block[64]) 0262 { 0263 0264 quint32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16]; 0265 0266 decode(x, block, 64); 0267 //memcpy( x, block, 64 ); 0268 0269 Q_ASSERT(!m_finalized); // not just a user error, since the method is private 0270 0271 /* Round 1 */ 0272 FF(a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */ 0273 FF(d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */ 0274 FF(c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */ 0275 FF(b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */ 0276 FF(a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */ 0277 FF(d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */ 0278 FF(c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */ 0279 FF(b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */ 0280 FF(a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */ 0281 FF(d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */ 0282 FF(c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */ 0283 FF(b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */ 0284 FF(a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */ 0285 FF(d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */ 0286 FF(c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */ 0287 FF(b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */ 0288 0289 /* Round 2 */ 0290 GG(a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */ 0291 GG(d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */ 0292 GG(c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */ 0293 GG(b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */ 0294 GG(a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */ 0295 GG(d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */ 0296 GG(c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */ 0297 GG(b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */ 0298 GG(a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */ 0299 GG(d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */ 0300 GG(c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */ 0301 GG(b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */ 0302 GG(a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */ 0303 GG(d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */ 0304 GG(c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */ 0305 GG(b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */ 0306 0307 /* Round 3 */ 0308 HH(a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */ 0309 HH(d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */ 0310 HH(c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */ 0311 HH(b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */ 0312 HH(a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */ 0313 HH(d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */ 0314 HH(c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */ 0315 HH(b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */ 0316 HH(a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */ 0317 HH(d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */ 0318 HH(c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */ 0319 HH(b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */ 0320 HH(a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */ 0321 HH(d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */ 0322 HH(c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */ 0323 HH(b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */ 0324 0325 /* Round 4 */ 0326 II(a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */ 0327 II(d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */ 0328 II(c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */ 0329 II(b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */ 0330 II(a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */ 0331 II(d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */ 0332 II(c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */ 0333 II(b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */ 0334 II(a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */ 0335 II(d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */ 0336 II(c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */ 0337 II(b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */ 0338 II(a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */ 0339 II(d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */ 0340 II(c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */ 0341 II(b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */ 0342 0343 m_state[0] += a; 0344 m_state[1] += b; 0345 m_state[2] += c; 0346 m_state[3] += d; 0347 0348 memset(static_cast<void *>(x), 0, sizeof(x)); 0349 } 0350 0351 inline quint32 KMD5::rotate_left(quint32 x, quint32 n) 0352 { 0353 return (x << n) | (x >> (32 - n)); 0354 } 0355 0356 inline quint32 KMD5::F(quint32 x, quint32 y, quint32 z) 0357 { 0358 return (x & y) | (~x & z); 0359 } 0360 0361 inline quint32 KMD5::G(quint32 x, quint32 y, quint32 z) 0362 { 0363 return (x & z) | (y & ~z); 0364 } 0365 0366 inline quint32 KMD5::H(quint32 x, quint32 y, quint32 z) 0367 { 0368 return x ^ y ^ z; 0369 } 0370 0371 inline quint32 KMD5::I(quint32 x, quint32 y, quint32 z) 0372 { 0373 return y ^ (x | ~z); 0374 } 0375 0376 void KMD5::FF(quint32 &a, quint32 b, quint32 c, quint32 d, 0377 quint32 x, quint32 s, quint32 ac) 0378 { 0379 a += F(b, c, d) + x + ac; 0380 a = rotate_left(a, s) + b; 0381 } 0382 0383 void KMD5::GG(quint32 &a, quint32 b, quint32 c, quint32 d, 0384 quint32 x, quint32 s, quint32 ac) 0385 { 0386 a += G(b, c, d) + x + ac; 0387 a = rotate_left(a, s) + b; 0388 } 0389 0390 void KMD5::HH(quint32 &a, quint32 b, quint32 c, quint32 d, 0391 quint32 x, quint32 s, quint32 ac) 0392 { 0393 a += H(b, c, d) + x + ac; 0394 a = rotate_left(a, s) + b; 0395 } 0396 0397 void KMD5::II(quint32 &a, quint32 b, quint32 c, quint32 d, 0398 quint32 x, quint32 s, quint32 ac) 0399 { 0400 a += I(b, c, d) + x + ac; 0401 a = rotate_left(a, s) + b; 0402 } 0403 0404 void KMD5::encode(unsigned char *output, quint32 *in, quint32 len) 0405 { 0406 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN 0407 memcpy(output, in, len); 0408 #else 0409 quint32 i, j; 0410 for (i = 0, j = 0; j < len; i++, j += 4) { 0411 output[j] = static_cast<quint8>((in[i] & 0xff)); 0412 output[j + 1] = static_cast<quint8>(((in[i] >> 8) & 0xff)); 0413 output[j + 2] = static_cast<quint8>(((in[i] >> 16) & 0xff)); 0414 output[j + 3] = static_cast<quint8>(((in[i] >> 24) & 0xff)); 0415 } 0416 #endif 0417 } 0418 0419 // Decodes in (quint8) into output (quint32). Assumes len is a 0420 // multiple of 4. 0421 void KMD5::decode(quint32 *output, const unsigned char *in, quint32 len) 0422 { 0423 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN 0424 memcpy(output, in, len); 0425 0426 #else 0427 quint32 i, j; 0428 for (i = 0, j = 0; j < len; i++, j += 4) 0429 output[i] = static_cast<quint32>(in[j]) | 0430 (static_cast<quint32>(in[j + 1]) << 8) | 0431 (static_cast<quint32>(in[j + 2]) << 16) | 0432 (static_cast<quint32>(in[j + 3]) << 24); 0433 #endif 0434 } 0435 0436 /**************************************************************/