Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/rsa/md5.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 #pragma once
0002 
0003 /* MD5
0004  converted to C++ class by Frank Thilo (thilo@unix-ag.org)
0005  for bzflag (http://www.bzflag.org)
0006 
0007    based on:
0008 
0009    md5.h and md5.c
0010    reference implementation of RFC 1321
0011 
0012    Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
0013 rights reserved.
0014 
0015 License to copy and use this software is granted provided that it
0016 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
0017 Algorithm" in all material mentioning or referencing this software
0018 or this function.
0019 
0020 License is also granted to make and use derivative works provided
0021 that such works are identified as "derived from the RSA Data
0022 Security, Inc. MD5 Message-Digest Algorithm" in all material
0023 mentioning or referencing the derived work.
0024 
0025 RSA Data Security, Inc. makes no representations concerning either
0026 the merchantability of this software or the suitability of this
0027 software for any particular purpose. It is provided "as is"
0028 without express or implied warranty of any kind.
0029 
0030 These notices must be retained in any copies of any part of this
0031 documentation and/or software.
0032 
0033 */
0034 
0035 #ifndef BZF_MD5_H
0036 #define BZF_MD5_H
0037 
0038 #include <cstring>
0039 #include <iostream>
0040 
0041 
0042 // a small class for calculating MD5 hashes of strings or byte arrays
0043 // it is not meant to be fast or secure
0044 //
0045 // usage: 1) feed it blocks of uchars with update()
0046 //      2) finalize()
0047 //      3) get hexdigest() string
0048 //      or
0049 //      MD5(std::string).hexdigest()
0050 //
0051 // assumes that char is 8 bit and int is 32 bit
0052 class MD5
0053 {
0054 public:
0055   typedef unsigned int size_type; // must be 32bit
0056 
0057   MD5();
0058   MD5(const std::string& text);
0059   void update(const unsigned char *buf, size_type length);
0060   void update(const char *buf, size_type length);
0061   MD5& finalize();
0062   std::string hexdigest() const;
0063   friend std::ostream& operator<<(std::ostream&, MD5 md5);
0064 
0065 private:
0066   void init();
0067   typedef unsigned char uint1; //  8bit
0068   typedef unsigned int uint4;  // 32bit
0069   enum {blocksize = 64}; // VC6 won't eat a const static int here
0070 
0071   void transform(const uint1 block[blocksize]);
0072   static void decode(uint4 output[], const uint1 input[], size_type len);
0073   static void encode(uint1 output[], const uint4 input[], size_type len);
0074 
0075   bool finalized;
0076   uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
0077   uint4 count[2];   // 64bit counter for number of bits (lo, hi)
0078   uint4 state[4];   // digest so far
0079   uint1 digest[16]; // the result
0080 
0081   // low level logic operations
0082   static inline uint4 F(uint4 x, uint4 y, uint4 z);
0083   static inline uint4 G(uint4 x, uint4 y, uint4 z);
0084   static inline uint4 H(uint4 x, uint4 y, uint4 z);
0085   static inline uint4 I(uint4 x, uint4 y, uint4 z);
0086   static inline uint4 rotate_left(uint4 x, int n);
0087   static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
0088   static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
0089   static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
0090   static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
0091 };
0092 
0093 std::string md5(const std::string str);
0094 
0095 #endif
0096 
0097 
0098 /* MD5
0099  converted to C++ class by Frank Thilo (thilo@unix-ag.org)
0100  for bzflag (http://www.bzflag.org)
0101 
0102    based on:
0103 
0104    md5.h and md5.c
0105    reference implemantion of RFC 1321
0106 
0107    Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
0108 rights reserved.
0109 
0110 License to copy and use this software is granted provided that it
0111 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
0112 Algorithm" in all material mentioning or referencing this software
0113 or this function.
0114 
0115 License is also granted to make and use derivative works provided
0116 that such works are identified as "derived from the RSA Data
0117 Security, Inc. MD5 Message-Digest Algorithm" in all material
0118 mentioning or referencing the derived work.
0119 
0120 RSA Data Security, Inc. makes no representations concerning either
0121 the merchantability of this software or the suitability of this
0122 software for any particular purpose. It is provided "as is"
0123 without express or implied warranty of any kind.
0124 
0125 These notices must be retained in any copies of any part of this
0126 documentation and/or software.
0127 
0128 */
0129 
0130 /* interface header */
0131 //#include "md5.h"
0132 
0133 /* system implementation headers */
0134 #include <cstdio>
0135 
0136 
0137 // Constants for MD5Transform routine.
0138 #define S11 7
0139 #define S12 12
0140 #define S13 17
0141 #define S14 22
0142 #define S21 5
0143 #define S22 9
0144 #define S23 14
0145 #define S24 20
0146 #define S31 4
0147 #define S32 11
0148 #define S33 16
0149 #define S34 23
0150 #define S41 6
0151 #define S42 10
0152 #define S43 15
0153 #define S44 21
0154 
0155 ///////////////////////////////////////////////
0156 
0157 // F, G, H and I are basic MD5 functions.
0158 inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
0159   return (x&y) | (~x&z);
0160 }
0161 
0162 inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
0163   return (x&z) | (y&~z);
0164 }
0165 
0166 inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
0167   return x^y^z;
0168 }
0169 
0170 inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
0171   return y ^ (x | ~z);
0172 }
0173 
0174 // rotate_left rotates x left n bits.
0175 inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
0176   return (x << n) | (x >> (32-n));
0177 }
0178 
0179 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
0180 // Rotation is separate from addition to prevent recomputation.
0181 inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
0182   a = rotate_left(a+ F(b,c,d) + x + ac, s) + b;
0183 }
0184 
0185 inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
0186   a = rotate_left(a + G(b,c,d) + x + ac, s) + b;
0187 }
0188 
0189 inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
0190   a = rotate_left(a + H(b,c,d) + x + ac, s) + b;
0191 }
0192 
0193 inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
0194   a = rotate_left(a + I(b,c,d) + x + ac, s) + b;
0195 }
0196 
0197 //////////////////////////////////////////////
0198 
0199 // default ctor, just initailize
0200 MD5::MD5()
0201 {
0202   init();
0203 }
0204 
0205 //////////////////////////////////////////////
0206 
0207 // nifty shortcut ctor, compute MD5 for string and finalize it right away
0208 MD5::MD5(const std::string &text)
0209 {
0210   init();
0211   update(text.c_str(), text.length());
0212   finalize();
0213 }
0214 
0215 //////////////////////////////
0216 
0217 void MD5::init()
0218 {
0219   finalized=false;
0220 
0221   count[0] = 0;
0222   count[1] = 0;
0223 
0224   // load magic initialization constants.
0225   state[0] = 0x67452301;
0226   state[1] = 0xefcdab89;
0227   state[2] = 0x98badcfe;
0228   state[3] = 0x10325476;
0229 }
0230 
0231 //////////////////////////////
0232 
0233 // decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
0234 void MD5::decode(uint4 output[], const uint1 input[], size_type len)
0235 {
0236   for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
0237     output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
0238       (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
0239 }
0240 
0241 //////////////////////////////
0242 
0243 // encodes input (uint4) into output (unsigned char). Assumes len is
0244 // a multiple of 4.
0245 void MD5::encode(uint1 output[], const uint4 input[], size_type len)
0246 {
0247   for (size_type i = 0, j = 0; j < len; i++, j += 4) {
0248     output[j] = input[i] & 0xff;
0249     output[j+1] = (input[i] >> 8) & 0xff;
0250     output[j+2] = (input[i] >> 16) & 0xff;
0251     output[j+3] = (input[i] >> 24) & 0xff;
0252   }
0253 }
0254 
0255 //////////////////////////////
0256 
0257 // apply MD5 algo on a block
0258 void MD5::transform(const uint1 block[blocksize])
0259 {
0260   uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
0261   decode (x, block, blocksize);
0262 
0263   /* Round 1 */
0264   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
0265   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
0266   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
0267   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
0268   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
0269   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
0270   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
0271   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
0272   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
0273   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
0274   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
0275   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
0276   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
0277   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
0278   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
0279   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
0280 
0281   /* Round 2 */
0282   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
0283   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
0284   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
0285   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
0286   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
0287   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
0288   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
0289   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
0290   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
0291   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
0292   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
0293   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
0294   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
0295   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
0296   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
0297   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
0298 
0299   /* Round 3 */
0300   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
0301   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
0302   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
0303   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
0304   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
0305   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
0306   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
0307   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
0308   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
0309   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
0310   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
0311   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
0312   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
0313   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
0314   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
0315   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
0316 
0317   /* Round 4 */
0318   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
0319   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
0320   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
0321   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
0322   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
0323   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
0324   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
0325   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
0326   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
0327   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
0328   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
0329   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
0330   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
0331   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
0332   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
0333   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
0334 
0335   state[0] += a;
0336   state[1] += b;
0337   state[2] += c;
0338   state[3] += d;
0339 
0340   // Zeroize sensitive information.
0341   memset(x, 0, sizeof x);
0342 }
0343 
0344 //////////////////////////////
0345 
0346 // MD5 block update operation. Continues an MD5 message-digest
0347 // operation, processing another message block
0348 void MD5::update(const unsigned char input[], size_type length)
0349 {
0350   // compute number of bytes mod 64
0351   size_type index = count[0] / 8 % blocksize;
0352 
0353   // Update number of bits
0354   if ((count[0] += (length << 3)) < (length << 3))
0355     count[1]++;
0356   count[1] += (length >> 29);
0357 
0358   // number of bytes we need to fill in buffer
0359   size_type firstpart = 64 - index;
0360 
0361   size_type i;
0362 
0363   // transform as many times as possible.
0364   if (length >= firstpart)
0365   {
0366     // fill buffer first, transform
0367     memcpy(&buffer[index], input, firstpart);
0368     transform(buffer);
0369 
0370     // transform chunks of blocksize (64 bytes)
0371     for (i = firstpart; i + blocksize <= length; i += blocksize)
0372       transform(&input[i]);
0373 
0374     index = 0;
0375   }
0376   else
0377     i = 0;
0378 
0379   // buffer remaining input
0380   memcpy(&buffer[index], &input[i], length-i);
0381 }
0382 
0383 //////////////////////////////
0384 
0385 // for convenience provide a verson with signed char
0386 void MD5::update(const char input[], size_type length)
0387 {
0388   update((const unsigned char*)input, length);
0389 }
0390 
0391 //////////////////////////////
0392 
0393 // MD5 finalization. Ends an MD5 message-digest operation, writing the
0394 // the message digest and zeroizing the context.
0395 MD5& MD5::finalize()
0396 {
0397   static unsigned char padding[64] = {
0398     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0399     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0400     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0401   };
0402 
0403   if (!finalized) {
0404     // Save number of bits
0405     unsigned char bits[8];
0406     encode(bits, count, 8);
0407 
0408     // pad out to 56 mod 64.
0409     size_type index = count[0] / 8 % 64;
0410     size_type padLen = (index < 56) ? (56 - index) : (120 - index);
0411     update(padding, padLen);
0412 
0413     // Append length (before padding)
0414     update(bits, 8);
0415 
0416     // Store state in digest
0417     encode(digest, state, 16);
0418 
0419     // Zeroize sensitive information.
0420     memset(buffer, 0, sizeof buffer);
0421     memset(count, 0, sizeof count);
0422 
0423     finalized=true;
0424   }
0425 
0426   return *this;
0427 }
0428 
0429 //////////////////////////////
0430 
0431 // return hex representation of digest as string
0432 std::string MD5::hexdigest() const
0433 {
0434   if (!finalized)
0435     return "";
0436 
0437   char buf[33];
0438   for (int i=0; i<16; i++)
0439     sprintf(buf+i*2, "%02x", digest[i]);
0440   buf[32]=0;
0441 
0442   return std::string(buf);
0443 }
0444 
0445 //////////////////////////////
0446 
0447 std::ostream& operator<<(std::ostream& out, MD5 md5)
0448 {
0449   return out << md5.hexdigest();
0450 }
0451 
0452 //////////////////////////////
0453 
0454 std::string md5(const std::string str)
0455 {
0456     MD5 md5 = MD5(str);
0457 
0458     return md5.hexdigest();
0459 }