-
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 Codemd5.cpp
1 #includemd5.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 = 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 for(int i = 0; i < 4; i++) //link A: low to high
77 {
78 md5Result_[i] = (A >> 8i) & 0 xff;
79 }
80 for(int i = 4; i<8; i++) //link B: low to high
81 {
82 md5Result_[i] = (B >> 8(i - 4)) & 0 xff;
83 }
84 for(int i = 8; i<12; i++) //link C: low to high
85 {
86 md5Result_[i] = (C >> 8(i - 8)) & 0 xff;
87 }
88 for(int 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 for(int 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 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], 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 x80, 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_ >> 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
原来,再大的房子,再大的床,没有相爱的人陪伴,都只是冰冷的物质。而如果身边有爱人陪伴,即使房子小,床小,也觉得无关紧要,因为这些物质上面有了爱的温度,成了家的元素。—— 何珞《婚房》#书摘#