用c++实现了md5算法。包含 md5.h 和md5.cpp 两个文件。
主要参考百度百科 “MD5” 原理的描述:http://baike.baidu.cn/view/7636.htm,代码中变量命名也是参考其中的公式,程序的使用说明在md5.h 文件的末尾注释中。
测试结果和百度百科测试例子一致。
实现过程中需要注意事项:最后把四个变量A B C D 链接成结果时 ,注意变量高低位的先后顺序,具体参考 LinkResult()方法。
md5.h
1 #ifndef _MD5_H_ 2 #define _MD5_H_ 3 4 #include <iostream> 5 #include <string> 6 using namespace std; 7 8 class MD5 9 { 10 public: 11 typedef unsigned char uchar8; //make sure it is 8bit 12 typedef char char8; //make sure it is 8bit 13 MD5(); 14 15 void init(); 16 17 void UpdateMd5(const uchar8 input[], const int length); 18 void UpdateMd5(const char8 input[], const int length); 19 20 void Finalize(); 21 22 void ComputMd5(const uchar8 input[], const int length); 23 void ComputMd5(const char8 input[], const int length); 24 25 string GetMd5(); 26 27 void printMd5(); 28 29 30 private: 31 typedef unsigned int uint32; //make sure it is 32 bit; 32 typedef unsigned long long uint64; //make sure it is 64 bit; 33 uint32 A, B, C, D; 34 const static int blockLen_ = 64; // 512/8 35 //the remain after last updata (because md5 may be computed segment by segment) 36 uchar8 remain_[blockLen_]; 37 int remainNum_ ; // the number of remain_, < 64 38 uint64 totalInputBits_; 39 uchar8 md5Result_[16]; //bit style md5 result,totally 128 bit 40 char md5Result_hex_[33]; //hexadecimal style result; md5Result_hex_[32]='\0' 41 bool isDone_; // indicate the comput is finished; 42 43 inline uint32 RotateLeft(const uint32 x, int n); 44 inline uint32 F(const uint32 x, const uint32 y, const uint32 z); 45 inline uint32 G(const uint32 x, const uint32 y, const uint32 z); 46 inline uint32 H(const uint32 x, const uint32 y, const uint32 z); 47 inline uint32 I(const uint32 x, const uint32 y, const uint32 z); 48 inline void FF(uint32 &a, const uint32 b, const uint32 c, const uint32 d, 49 const uint32 Mj, const int s, const uint32 ti); 50 inline void GG(uint32 &a, const uint32 b, const uint32 c, const uint32 d, 51 const uint32 Mj, const int s, const uint32 ti); 52 inline void HH(uint32 &a, const uint32 b, const uint32 c, const uint32 d, 53 const uint32 Mj, const int s, const uint32 ti); 54 inline void II(uint32 &a, const uint32 b, const uint32 c, const uint32 d, 55 const uint32 Mj, const int s, const uint32 ti); 56 57 58 void UcharToUint(uint32 output[], const uchar8 input[], const unsigned int transLength); 59 60 void FourRound(const uchar8 block[]); 61 62 void LinkResult(); 63 64 }; 65 66 /* user guide 67 you can comput the md5 by using the funtion ComputMd5 68 eg: 69 MD5 m; 70 MD5::char8 str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 71 m.ComputMd5(str,sizeof(str) - 1); 72 m.printMd5(); 73 74 if you want to comput segment by segment,you can do as follow, and init() is suggested 75 the begging,and Finalize() must call in the end: 76 77 MD5 M; 78 m.init(); 79 MD5::uchar8 str1[] = "ABCDEFGHIJKLMN"; 80 MD5::uchar8 str2[] = "OPQRSTUVWXYZabcdefghijk"; 81 MD5::uchar8 str3[] = "lmnopqrstuvwxyz"; 82 m.UpdateMd5(str1,sizeof(str1) - 1); 83 m.UpdateMd5(str2,sizeof(str2) - 1); 84 m.UpdateMd5(str3,sizeof(str3) - 1); 85 m.Finalize(); 86 m.printMd5(); 87 88 if you want to comput the md5 of a file, you can use the interface of this program. 89 */ 90 91 #endif
md5.cpp
1 #include"md5.h" 2 3 #include<iostream> 4 using namespace std; 5 6 const int S[4][4] = {7, 12, 17, 22, 7 5, 9, 14, 20, 8 4, 11, 16, 23, 9 6, 10, 15, 21}; 10 void MD5::init() 11 { 12 A = 0x67452301; 13 B = 0xefcdab89; 14 C = 0x98badcfe; 15 D = 0x10325476; 16 remainNum_ = 0; 17 remain_[0] = '\0'; 18 md5Result_hex_[0] = '\0'; 19 md5Result_[0] = '\0'; 20 totalInputBits_ = 0; 21 isDone_ = false; 22 } 23 24 MD5::MD5() 25 { 26 init(); 27 } 28 29 inline MD5::uint32 MD5::RotateLeft(const uint32 x, int n) 30 { 31 return (x << n) | (x >> (32-n)); 32 // if x is signed, use: (x << n) | ((x & 0xFFFFFFFF) >> (32-n)) 33 } 34 inline MD5::uint32 MD5::F(const uint32 x, const uint32 y, const uint32 z) 35 { 36 return (x & y) | ((~x) & z); 37 } 38 inline MD5::uint32 MD5::G(const uint32 x, const uint32 y, const uint32 z) 39 { 40 return (x & z) | (y & (~z)); 41 } 42 inline MD5::uint32 MD5::H(const uint32 x, const uint32 y, const uint32 z) 43 { 44 return x ^ y ^ z; 45 } 46 inline MD5::uint32 MD5::I(const uint32 x, const uint32 y, const uint32 z) 47 { 48 return y ^ (x | (~z)); 49 } 50 51 inline void MD5::FF(uint32 &a, const uint32 b, const uint32 c, const uint32 d, 52 const uint32 Mj, const int s, const uint32 ti) 53 { 54 a = b + RotateLeft(a + F(b, c, d) + Mj + ti, s); 55 } 56 inline void MD5::GG(uint32 &a, const uint32 b, const uint32 c, const uint32 d, 57 const uint32 Mj, const int s, const uint32 ti) 58 { 59 a = b + RotateLeft(a + G(b, c, d) + Mj + ti, s); 60 } 61 inline void MD5::HH(uint32 &a, const uint32 b, const uint32 c, const uint32 d, 62 const uint32 Mj, const int s, const uint32 ti) 63 { 64 a = b + RotateLeft(a + H(b, c, d) + Mj + ti, s); 65 } 66 inline void MD5::II(uint32 &a, const uint32 b, const uint32 c, const uint32 d, 67 const uint32 Mj, const int s, const uint32 ti) 68 { 69 a = b + RotateLeft(a + I(b, c, d) + Mj + ti, s); 70 } 71 72 // link A B C D to result(bit style result and hexadecimal style result) 73 void MD5::LinkResult() 74 { 75 //bit style result 76 for(int i = 0; i < 4; i++) //link A: low to high 77 { 78 md5Result_[i] = (A >> 8*i) & 0xff; 79 } 80 for(int i = 4; i<8; i++) //link B: low to high 81 { 82 md5Result_[i] = (B >> 8*(i - 4)) & 0xff; 83 } 84 for(int i = 8; i<12; i++) //link C: low to high 85 { 86 md5Result_[i] = (C >> 8*(i - 8)) & 0xff; 87 } 88 for(int i = 12; i<16; i++) //link D: low to high 89 { 90 md5Result_[i] = (D >> 8*(i - 12)) & 0xff; 91 } 92 93 //change to hexadecimal style result 94 // note: it is not the same as simply link hex(A) hex(B) hex(C) hex(D) 95 for(int i = 0; i < 16; i++) 96 sprintf(& md5Result_hex_[i*2], "%02x", md5Result_[i]); 97 md5Result_hex_[32] = '\0'; 98 99 } 100 101 //print the md5 by hex 102 void MD5::printMd5() 103 { 104 if(!isDone_) 105 { 106 cout<< "Error: computation is not finished" <<endl; 107 108 } 109 else 110 cout<< "MD5 Value: " << md5Result_hex_ <<endl; 111 } 112 113 //get the md5 value of hex style 114 string MD5::GetMd5() 115 { 116 if(!isDone_) 117 { 118 cout<< "Error: computation is not finished" <<endl; 119 exit(0); 120 } 121 string a((const char *)md5Result_hex_); 122 return a; 123 } 124 125 void MD5::UcharToUint(uint32 output[], const uchar8 input[], const unsigned int transLength) 126 { 127 for(int i = 0, j = 0; j < transLength; i++, j += 4) 128 { 129 output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) | 130 (((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24); 131 } 132 } 133 134 // four round on a block of 512 bits; 135 void MD5::FourRound(const uchar8 block[]) 136 { 137 uint32 a = A, b = B, c = C, d = D; 138 uint32 M[16]; 139 UcharToUint(M, block, blockLen_); //blockLen_ is a const int =64; 140 141 //round 1 142 FF (a, b, c, d, M[ 0], S[0][0], 0xd76aa478); 143 FF (d, a, b, c, M[ 1], S[0][1], 0xe8c7b756); 144 FF (c, d, a, b, M[ 2], S[0][2], 0x242070db); 145 FF (b, c, d, a, M[ 3], S[0][3], 0xc1bdceee); 146 FF (a, b, c, d, M[ 4], S[0][0], 0xf57c0faf); 147 FF (d, a, b, c, M[ 5], S[0][1], 0x4787c62a); 148 FF (c, d, a, b, M[ 6], S[0][2], 0xa8304613); 149 FF (b, c, d, a, M[ 7], S[0][3], 0xfd469501); 150 FF (a, b, c, d, M[ 8], S[0][0], 0x698098d8); 151 FF (d, a, b, c, M[ 9], S[0][1], 0x8b44f7af); 152 FF (c, d, a, b, M[10], S[0][2], 0xffff5bb1); 153 FF (b, c, d, a, M[11], S[0][3], 0x895cd7be); 154 FF (a, b, c, d, M[12], S[0][0], 0x6b901122); 155 FF (d, a, b, c, M[13], S[0][1], 0xfd987193); 156 FF (c, d, a, b, M[14], S[0][2], 0xa679438e); 157 FF (b, c, d, a, M[15], S[0][3], 0x49b40821); 158 159 // round 2 160 GG (a, b, c, d, M[ 1], S[1][0], 0xf61e2562); 161 GG (d, a, b, c, M[ 6], S[1][1], 0xc040b340); 162 GG (c, d, a, b, M[11], S[1][2], 0x265e5a51); 163 GG (b, c, d, a, M[ 0], S[1][3], 0xe9b6c7aa); 164 GG (a, b, c, d, M[ 5], S[1][0], 0xd62f105d); 165 GG (d, a, b, c, M[10], S[1][1], 0x2441453); 166 GG (c, d, a, b, M[15], S[1][2], 0xd8a1e681); 167 GG (b, c, d, a, M[ 4], S[1][3], 0xe7d3fbc8); 168 GG (a, b, c, d, M[ 9], S[1][0], 0x21e1cde6); 169 GG (d, a, b, c, M[14], S[1][1], 0xc33707d6); 170 GG (c, d, a, b, M[ 3], S[1][2], 0xf4d50d87); 171 GG (b, c, d, a, M[ 8], S[1][3], 0x455a14ed); 172 GG (a, b, c, d, M[13], S[1][0], 0xa9e3e905); 173 GG (d, a, b, c, M[ 2], S[1][1], 0xfcefa3f8); 174 GG (c, d, a, b, M[ 7], S[1][2], 0x676f02d9); 175 GG (b, c, d, a, M[12], S[1][3], 0x8d2a4c8a); 176 177 //round 3 178 HH (a, b, c, d, M[ 5], S[2][0], 0xfffa3942); 179 HH (d, a, b, c, M[ 8], S[2][1], 0x8771f681); 180 HH (c, d, a, b, M[11], S[2][2], 0x6d9d6122); 181 HH (b, c, d, a, M[14], S[2][3], 0xfde5380c); 182 HH (a, b, c, d, M[ 1], S[2][0], 0xa4beea44); 183 HH (d, a, b, c, M[ 4], S[2][1], 0x4bdecfa9); 184 HH (c, d, a, b, M[ 7], S[2][2], 0xf6bb4b60); 185 HH (b, c, d, a, M[10], S[2][3], 0xbebfbc70); 186 HH (a, b, c, d, M[13], S[2][0], 0x289b7ec6); 187 HH (d, a, b, c, M[ 0], S[2][1], 0xeaa127fa); 188 HH (c, d, a, b, M[ 3], S[2][2], 0xd4ef3085); 189 HH (b, c, d, a, M[ 6], S[2][3], 0x4881d05); 190 HH (a, b, c, d, M[ 9], S[2][0], 0xd9d4d039); 191 HH (d, a, b, c, M[12], S[2][1], 0xe6db99e5); 192 HH (c, d, a, b, M[15], S[2][2], 0x1fa27cf8); 193 HH (b, c, d, a, M[ 2], S[2][3], 0xc4ac5665); 194 195 //round 4 196 II (a, b, c, d, M[ 0], S[3][0], 0xf4292244); 197 II (d, a, b, c, M[ 7], S[3][1], 0x432aff97); 198 II (c, d, a, b, M[14], S[3][2], 0xab9423a7); 199 II (b, c, d, a, M[ 5], S[3][3], 0xfc93a039); 200 II (a, b, c, d, M[12], S[3][0], 0x655b59c3); 201 II (d, a, b, c, M[ 3], S[3][1], 0x8f0ccc92); 202 II (c, d, a, b, M[10], S[3][2], 0xffeff47d); 203 II (b, c, d, a, M[ 1], S[3][3], 0x85845dd1); 204 II (a, b, c, d, M[ 8], S[3][0], 0x6fa87e4f); 205 II (d, a, b, c, M[15], S[3][1], 0xfe2ce6e0); 206 II (c, d, a, b, M[ 6], S[3][2], 0xa3014314); 207 II (b, c, d, a, M[13], S[3][3], 0x4e0811a1); 208 II (a, b, c, d, M[ 4], S[3][0], 0xf7537e82); 209 II (d, a, b, c, M[11], S[3][1], 0xbd3af235); 210 II (c, d, a, b, M[ 2], S[3][2], 0x2ad7d2bb); 211 II (b, c, d, a, M[ 9], S[3][3], 0xeb86d391); 212 213 A += a; 214 B += b; 215 C += c; 216 D += d; 217 } 218 219 // update md5,must consider the remain_. 220 void MD5::UpdateMd5(const uchar8 input[], const int length) 221 { 222 isDone_ = false; 223 totalInputBits_ += (length << 3); 224 225 int start = blockLen_ - remainNum_; //blockLen_ = 64 226 //copy a part of input to remain_ so it can form a block(size=64) 227 228 if(start <= length) 229 { 230 // can form a block,then do FourRound to this block 231 memcpy(&remain_[remainNum_], input, start) ; 232 FourRound(remain_); 233 234 int i; 235 for(i = start; i <= length - blockLen_; i += blockLen_) 236 { 237 FourRound(&input[i]); 238 } 239 remainNum_ = length - i; 240 memcpy(remain_, &input[i], remainNum_); 241 } 242 else 243 { 244 // can not form a block, function return; 245 memcpy(&remain_[remainNum_], input, length); 246 remainNum_ += length; 247 } 248 249 } 250 251 void MD5::UpdateMd5(const char8 input[], const int length) 252 { 253 UpdateMd5((const uchar8 *)input, length); 254 } 255 256 // padding with 100000... to remain_ and add the 64bit original size of input 257 void MD5::Finalize() 258 { 259 if(isDone_ == true) 260 return; 261 262 uchar8 padding[64] = { 263 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 264 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 265 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 266 }; 267 268 int temp = 56 - remainNum_; //56 = 448/8 269 if(temp > 0) 270 { 271 UpdateMd5(padding, temp); 272 totalInputBits_ -= (temp << 3); 273 } 274 else if(temp < 0) 275 { 276 UpdateMd5(padding, 64 + temp); 277 totalInputBits_ -= ((64 + temp) << 3); 278 } 279 280 // trans totalInputBits_ to uchar8 (64bits) 281 uchar8 Bits[8]; 282 for(int i = 0; i < 8; i++) 283 { 284 Bits[i] = (totalInputBits_ >> 8*i) & 0xff; 285 } 286 287 UpdateMd5(Bits, 8); // add the number of original input (the last 64bits) 288 289 LinkResult(); 290 isDone_ = true; 291 } 292 293 // comput the md5 based on input, (just this one input) 294 void MD5::ComputMd5(const uchar8 input[], const int length) 295 { 296 init(); 297 UpdateMd5(input, length); 298 Finalize(); 299 } 300 301 void MD5::ComputMd5(const char8 input[], const int length) 302 { 303 ComputMd5((const uchar8 *)input, length); 304 }
【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/archive/2013/06/02/3114056.html