MD5 算法实现(c++)

用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 #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 }
View Code

 【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/archive/2013/06/02/3114056.html

你可能感兴趣的:(C++)