MD5 算法实现(c++)

    添加时间:2013-6-2 点击量:

    用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


    View Code

    md5.cpp




      1 #includemd5.h
    
    2
    3 #include<iostream>
    4 using namespace std;
    5
    6 const int S[4][4] = {7121722
    7 591420
    8 4111623
    9 6101521};
    10 void MD5::init()
    11 {
    12 A = 0 x67452301;
    13 B = 0 xefcdab89;
    14 C = 0 x98badcfe;
    15 D = 0 x10325476;
    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 & 0 xFFFFFFFF) >> (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 forint i = 0; i < 4; i++) //link A: low to high
    77 {
    78 md5Result_[i] = (A >> 8i) & 0 xff;
    79 }
    80 forint i = 4; i<8; i++) //link B: low to high
    81 {
    82 md5Result_[i] = (B >> 8(i - 4)) & 0 xff;
    83 }
    84 forint i = 8; i<12; i++) //link C: low to high
    85 {
    86 md5Result_[i] = (C >> 8(i - 8)) & 0 xff;
    87 }
    88 forint i = 12; i<16; i++) //link D: low to high
    89 {
    90 md5Result_[i] = (D >> 8(i - 12)) & 0 xff;
    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 forint i = 0; i < 16; i++
    96 sprintf(& md5Result_hex_[i2], %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 forint 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], 0 xd76aa478);
    143 FF (d, a, b, c, M[ 1], S[0][1], 0 xe8c7b756);
    144 FF (c, d, a, b, M[ 2], S[0][2], 0 x242070db);
    145 FF (b, c, d, a, M[ 3], S[0][3], 0 xc1bdceee);
    146 FF (a, b, c, d, M[ 4], S[0][0], 0 xf57c0faf);
    147 FF (d, a, b, c, M[ 5], S[0][1], 0 x4787c62a);
    148 FF (c, d, a, b, M[ 6], S[0][2], 0 xa8304613);
    149 FF (b, c, d, a, M[ 7], S[0][3], 0 xfd469501);
    150 FF (a, b, c, d, M[ 8], S[0][0], 0 x698098d8);
    151 FF (d, a, b, c, M[ 9], S[0][1], 0 x8b44f7af);
    152 FF (c, d, a, b, M[10], S[0][2], 0 xffff5bb1);
    153 FF (b, c, d, a, M[11], S[0][3], 0 x895cd7be);
    154 FF (a, b, c, d, M[12], S[0][0], 0 x6b901122);
    155 FF (d, a, b, c, M[13], S[0][1], 0 xfd987193);
    156 FF (c, d, a, b, M[14], S[0][2], 0 xa679438e);
    157 FF (b, c, d, a, M[15], S[0][3], 0 x49b40821);
    158
    159 // round 2
    160 GG (a, b, c, d, M[ 1], S[1][0], 0 xf61e2562);
    161 GG (d, a, b, c, M[ 6], S[1][1], 0 xc040b340);
    162 GG (c, d, a, b, M[11], S[1][2], 0 x265e5a51);
    163 GG (b, c, d, a, M[ 0], S[1][3], 0 xe9b6c7aa);
    164 GG (a, b, c, d, M[ 5], S[1][0], 0 xd62f105d);
    165 GG (d, a, b, c, M[10], S[1][1], 0 x2441453);
    166 GG (c, d, a, b, M[15], S[1][2], 0 xd8a1e681);
    167 GG (b, c, d, a, M[ 4], S[1][3], 0 xe7d3fbc8);
    168 GG (a, b, c, d, M[ 9], S[1][0], 0 x21e1cde6);
    169 GG (d, a, b, c, M[14], S[1][1], 0 xc33707d6);
    170 GG (c, d, a, b, M[ 3], S[1][2], 0 xf4d50d87);
    171 GG (b, c, d, a, M[ 8], S[1][3], 0 x455a14ed);
    172 GG (a, b, c, d, M[13], S[1][0], 0 xa9e3e905);
    173 GG (d, a, b, c, M[ 2], S[1][1], 0 xfcefa3f8);
    174 GG (c, d, a, b, M[ 7], S[1][2], 0 x676f02d9);
    175 GG (b, c, d, a, M[12], S[1][3], 0 x8d2a4c8a);
    176
    177 //round 3
    178 HH (a, b, c, d, M[ 5], S[2][0], 0 xfffa3942);
    179 HH (d, a, b, c, M[ 8], S[2][1], 0 x8771f681);
    180 HH (c, d, a, b, M[11], S[2][2], 0 x6d9d6122);
    181 HH (b, c, d, a, M[14], S[2][3], 0 xfde5380c);
    182 HH (a, b, c, d, M[ 1], S[2][0], 0 xa4beea44);
    183 HH (d, a, b, c, M[ 4], S[2][1], 0 x4bdecfa9);
    184 HH (c, d, a, b, M[ 7], S[2][2], 0 xf6bb4b60);
    185 HH (b, c, d, a, M[10], S[2][3], 0 xbebfbc70);
    186 HH (a, b, c, d, M[13], S[2][0], 0 x289b7ec6);
    187 HH (d, a, b, c, M[ 0], S[2][1], 0 xeaa127fa);
    188 HH (c, d, a, b, M[ 3], S[2][2], 0 xd4ef3085);
    189 HH (b, c, d, a, M[ 6], S[2][3], 0 x4881d05);
    190 HH (a, b, c, d, M[ 9], S[2][0], 0 xd9d4d039);
    191 HH (d, a, b, c, M[12], S[2][1], 0 xe6db99e5);
    192 HH (c, d, a, b, M[15], S[2][2], 0 x1fa27cf8);
    193 HH (b, c, d, a, M[ 2], S[2][3], 0 xc4ac5665);
    194
    195 //round 4
    196 II (a, b, c, d, M[ 0], S[3][0], 0 xf4292244);
    197 II (d, a, b, c, M[ 7], S[3][1], 0 x432aff97);
    198 II (c, d, a, b, M[14], S[3][2], 0 xab9423a7);
    199 II (b, c, d, a, M[ 5], S[3][3], 0 xfc93a039);
    200 II (a, b, c, d, M[12], S[3][0], 0 x655b59c3);
    201 II (d, a, b, c, M[ 3], S[3][1], 0 x8f0ccc92);
    202 II (c, d, a, b, M[10], S[3][2], 0 xffeff47d);
    203 II (b, c, d, a, M[ 1], S[3][3], 0 x85845dd1);
    204 II (a, b, c, d, M[ 8], S[3][0], 0 x6fa87e4f);
    205 II (d, a, b, c, M[15], S[3][1], 0 xfe2ce6e0);
    206 II (c, d, a, b, M[ 6], S[3][2], 0 xa3014314);
    207 II (b, c, d, a, M[13], S[3][3], 0 x4e0811a1);
    208 II (a, b, c, d, M[ 4], S[3][0], 0 xf7537e82);
    209 II (d, a, b, c, M[11], S[3][1], 0 xbd3af235);
    210 II (c, d, a, b, M[ 2], S[3][2], 0 x2ad7d2bb);
    211 II (b, c, d, a, M[ 9], S[3][3], 0 xeb86d391);
    212
    213 A += a;
    214 B += b;
    215 C += c;
    216 D += d;
    217 }
    218
    219 // 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 0 x80000000000000000000000
    264 00000000000000000000000
    265 0000000000000000000
    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 forint i = 0; i < 8; i++
    283 {
    284 Bits[i] = (totalInputBits_ >> 8i) & 0 xff;
    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 }


    View Code

    原来,再大的房子,再大的床,没有相爱的人陪伴,都只是冰冷的物质。而如果身边有爱人陪伴,即使房子小,床小,也觉得无关紧要,因为这些物质上面有了爱的温度,成了家的元素。—— 何珞《婚房》#书摘#
    分享到: