File indexing completed on 2024-03-24 15:27:25

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 /**************************************************************/