1 /////////////////////////////////////////////////////////////////////////
2 // MD5.cpp
3 // Implementation file for MD5 class
4 //
5 // This C++ Class implementation of the original RSA Data Security, Inc.
6 // MD5 Message-Digest Algorithm is copyright (c) 2002, Gary McNickle.
7 // All rights reserved. This software is a derivative of the "RSA Data
8 // Security, Inc. MD5 Message-Digest Algorithm"
9 //
10 // You may use this software free of any charge, but without any
11 // warranty or implied warranty, provided that you follow the terms
12 // of the original RSA copyright, listed below.
13 //
14 // Original RSA Data Security, Inc. Copyright notice
15 /////////////////////////////////////////////////////////////////////////
16 //
17 // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
18 // rights reserved.
19 //
20 // License to copy and use this software is granted provided that it
21 // is identified as the "RSA Data Security, Inc. MD5 Message-Digest
22 // Algorithm" in all material mentioning or referencing this software
23 // or this function.
24 // License is also granted to make and use derivative works provided
25 // that such works are identified as "derived from the RSA Data
26 // Security, Inc. MD5 Message-Digest Algorithm" in all material
27 // mentioning or referencing the derived work.
28 // RSA Data Security, Inc. makes no representations concerning either
29 // the merchantability of this software or the suitability of this
30 // software for any particular purpose. It is provided "as is"
31 // without express or implied warranty of any kind.
32 // These notices must be retained in any copies of any part of this
33 // documentation and/or software.
34 /////////////////////////////////////////////////////////////////////////
35
36 /*------------------------------------------------------------------------------
37 * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
38 *
39 * Distributable under the terms of either the Apache License (Version 2.0) or
40 * the GNU Lesser General Public License, as specified in the COPYING file.
41 ------------------------------------------------------------------------------*/
42
43 #include "CLucene/_ApiHeader.h"
44 #include "_MD5Digester.h"
45 CL_NS_DEF(util)
46
47 static unsigned char PADDING[64] =
48 {
49 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
52 };
53
54 #define S11 7
55 #define S12 12
56 #define S13 17
57 #define S14 22
58 #define S21 5
59 #define S22 9
60 #define S23 14
61 #define S24 20
62 #define S31 4
63 #define S32 11
64 #define S33 16
65 #define S34 23
66 #define S41 6
67 #define S42 10
68 #define S43 15
69 #define S44 21
70
71
72 // PrintMD5: Converts a completed md5 digest into a char* string.
PrintMD5(uint8_t md5Digest[16])73 char* PrintMD5(uint8_t md5Digest[16])
74 {
75 const char toHex[] = "0123456789abcdef";
76 char chBuffer[16 * 2 + 1];
77 int nCount;
78
79 for (nCount = 0; nCount < 16; nCount++)
80 {
81 chBuffer[nCount * 2] = toHex[(md5Digest[nCount] & 0xf0) >> 4];
82 chBuffer[nCount * 2 + 1] = toHex[md5Digest[nCount] & 0x0f];
83 }
84 chBuffer[nCount * 2] = '\0';
85
86 return STRDUP_AtoA(chBuffer);
87 }
88
89 // MD5String: Performs the MD5 algorithm on a char* string, returning
90 // the results as a char*.
MD5String(char * szString)91 char* MD5String(char* szString)
92 {
93 int nLen = strlen(szString);
94 md5 alg;
95
96 alg.Update((unsigned char*)szString, (unsigned int)nLen);
97 alg.Finalize();
98
99 return PrintMD5(alg.Digest());
100
101 }
102
103 // MD5File: Performs the MD5 algorithm on a file (binar or text),
104 // returning the results as a char*. Returns NULL if it fails.
MD5File(char * szFilename)105 char* MD5File(char* szFilename)
106 {
107 FILE* file;
108 md5 alg;
109 int nLen;
110 unsigned char chBuffer[1024];
111
112 try
113 {
114 memset(chBuffer, 0, 1024);
115
116 if ((file = fopen (szFilename, "rb")) != NULL)
117 {
118 while ((nLen = fread (chBuffer, 1, 1024, file)))
119 alg.Update(chBuffer, nLen);
120
121 alg.Finalize();
122
123 fclose (file);
124
125 return PrintMD5(alg.Digest());
126 }
127 }
128 catch(...) //todo: only catch IO Err???
129 {
130
131 }
132
133 return NULL; // failed
134 }
135
136
137 // md5::Init
138 // Initializes a new context.
Init()139 void md5::Init()
140 {
141 memset(m_Count, 0, 2 * sizeof(uint32_t));
142
143 m_State[0] = 0x67452301;
144 m_State[1] = 0xefcdab89;
145 m_State[2] = 0x98badcfe;
146 m_State[3] = 0x10325476;
147 }
148
149 // md5::Update
150 // MD5 block update operation. Continues an MD5 message-digest
151 // operation, processing another message block, and updating the
152 // context.
Update(uint8_t * chInput,uint32_t nInputLen)153 void md5::Update(uint8_t* chInput, uint32_t nInputLen)
154 {
155 uint32_t i, index, partLen;
156
157 // Compute number of bytes mod 64
158 index = (unsigned int)((m_Count[0] >> 3) & 0x3F);
159
160 // Update number of bits
161 if ((m_Count[0] += (nInputLen << 3)) < (nInputLen << 3))
162 m_Count[1]++;
163
164 m_Count[1] += (nInputLen >> 29);
165
166 partLen = 64 - index;
167
168 // Transform as many times as possible.
169 if (nInputLen >= partLen)
170 {
171 memcpy( &m_Buffer[index], chInput, partLen );
172 Transform(m_Buffer);
173
174 for (i = partLen; i + 63 < nInputLen; i += 64)
175 Transform(&chInput[i]);
176
177 index = 0;
178 }
179 else
180 i = 0;
181
182 // Buffer remaining input
183 memcpy( &m_Buffer[index], &chInput[i], nInputLen-i );
184 }
185
186 // md5::Finalize
187 // MD5 finalization. Ends an MD5 message-digest operation, writing
188 // the message digest and zeroizing the context.
Finalize()189 void md5::Finalize()
190 {
191 uint8_t bits[8];
192 uint32_t index, padLen;
193
194 // Save number of bits
195 Encode (bits, m_Count, 8);
196
197 // Pad out to 56 mod 64
198 index = (unsigned int)((m_Count[0] >> 3) & 0x3f);
199 padLen = (index < 56) ? (56 - index) : (120 - index);
200 Update(PADDING, padLen);
201
202 // Append length (before padding)
203 Update (bits, 8);
204
205 // Store state in digest
206 Encode (m_Digest, m_State, 16);
207
208 memset(m_Count, 0, 2 * sizeof(uint32_t));
209 memset(m_State, 0, 4 * sizeof(uint32_t));
210 memset(m_Buffer,0, 64 * sizeof(uint8_t));
211 }
212
213 // md5::Transform
214 // MD5 basic transformation. Transforms state based on block.
Transform(uint8_t * block)215 void md5::Transform (uint8_t* block)
216 {
217 uint32_t a = m_State[0], b = m_State[1], c = m_State[2], d = m_State[3], x[16];
218
219 Decode (x, block, 64);
220
221 // Round 1
222 FF (a, b, c, d, x[ 0], S11, 0xd76aa478);
223 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756);
224 FF (c, d, a, b, x[ 2], S13, 0x242070db);
225 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee);
226 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf);
227 FF (d, a, b, c, x[ 5], S12, 0x4787c62a);
228 FF (c, d, a, b, x[ 6], S13, 0xa8304613);
229 FF (b, c, d, a, x[ 7], S14, 0xfd469501);
230 FF (a, b, c, d, x[ 8], S11, 0x698098d8);
231 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af);
232 FF (c, d, a, b, x[10], S13, 0xffff5bb1);
233 FF (b, c, d, a, x[11], S14, 0x895cd7be);
234 FF (a, b, c, d, x[12], S11, 0x6b901122);
235 FF (d, a, b, c, x[13], S12, 0xfd987193);
236 FF (c, d, a, b, x[14], S13, 0xa679438e);
237 FF (b, c, d, a, x[15], S14, 0x49b40821);
238
239 // Round 2
240 GG (a, b, c, d, x[ 1], S21, 0xf61e2562);
241 GG (d, a, b, c, x[ 6], S22, 0xc040b340);
242 GG (c, d, a, b, x[11], S23, 0x265e5a51);
243 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
244 GG (a, b, c, d, x[ 5], S21, 0xd62f105d);
245 GG (d, a, b, c, x[10], S22, 0x2441453);
246 GG (c, d, a, b, x[15], S23, 0xd8a1e681);
247 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
248 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6);
249 GG (d, a, b, c, x[14], S22, 0xc33707d6);
250 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87);
251 GG (b, c, d, a, x[ 8], S24, 0x455a14ed);
252 GG (a, b, c, d, x[13], S21, 0xa9e3e905);
253 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8);
254 GG (c, d, a, b, x[ 7], S23, 0x676f02d9);
255 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);
256
257 // Round 3
258 HH (a, b, c, d, x[ 5], S31, 0xfffa3942);
259 HH (d, a, b, c, x[ 8], S32, 0x8771f681);
260 HH (c, d, a, b, x[11], S33, 0x6d9d6122);
261 HH (b, c, d, a, x[14], S34, 0xfde5380c);
262 HH (a, b, c, d, x[ 1], S31, 0xa4beea44);
263 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9);
264 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60);
265 HH (b, c, d, a, x[10], S34, 0xbebfbc70);
266 HH (a, b, c, d, x[13], S31, 0x289b7ec6);
267 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa);
268 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085);
269 HH (b, c, d, a, x[ 6], S34, 0x4881d05);
270 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039);
271 HH (d, a, b, c, x[12], S32, 0xe6db99e5);
272 HH (c, d, a, b, x[15], S33, 0x1fa27cf8);
273 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665);
274
275 // Round 4
276 II (a, b, c, d, x[ 0], S41, 0xf4292244);
277 II (d, a, b, c, x[ 7], S42, 0x432aff97);
278 II (c, d, a, b, x[14], S43, 0xab9423a7);
279 II (b, c, d, a, x[ 5], S44, 0xfc93a039);
280 II (a, b, c, d, x[12], S41, 0x655b59c3);
281 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92);
282 II (c, d, a, b, x[10], S43, 0xffeff47d);
283 II (b, c, d, a, x[ 1], S44, 0x85845dd1);
284 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f);
285 II (d, a, b, c, x[15], S42, 0xfe2ce6e0);
286 II (c, d, a, b, x[ 6], S43, 0xa3014314);
287 II (b, c, d, a, x[13], S44, 0x4e0811a1);
288 II (a, b, c, d, x[ 4], S41, 0xf7537e82);
289 II (d, a, b, c, x[11], S42, 0xbd3af235);
290 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
291 II (b, c, d, a, x[ 9], S44, 0xeb86d391);
292
293 m_State[0] += a;
294 m_State[1] += b;
295 m_State[2] += c;
296 m_State[3] += d;
297
298 memset(x, 0, sizeof(x));
299 }
300
301 // md5::Encode
302 // Encodes input (uint32_t) into output (uint8_t). Assumes nLength is
303 // a multiple of 4.
Encode(uint8_t * dest,uint32_t * src,uint32_t nLength)304 void md5::Encode(uint8_t* dest, uint32_t* src, uint32_t nLength)
305 {
306 uint32_t i, j;
307
308 CND_PRECONDITION(nLength % 4 == 0,"nLength % 4 != 0")
309
310 for (i = 0, j = 0; j < nLength; i++, j += 4)
311 {
312 dest[j] = (uint8_t)(src[i] & 0xff);
313 dest[j+1] = (uint8_t)((src[i] >> 8) & 0xff);
314 dest[j+2] = (uint8_t)((src[i] >> 16) & 0xff);
315 dest[j+3] = (uint8_t)((src[i] >> 24) & 0xff);
316 }
317 }
318
319 // md5::Decode
320 // Decodes input (uint8_t) into output (uint32_t). Assumes nLength is
321 // a multiple of 4.
Decode(uint32_t * dest,uint8_t * src,uint32_t nLength)322 void md5::Decode(uint32_t* dest, uint8_t* src, uint32_t nLength)
323 {
324 uint32_t i, j;
325
326 CND_PRECONDITION(nLength % 4 == 0, "nLength % 4 != 0");
327
328 for (i = 0, j = 0; j < nLength; i++, j += 4)
329 {
330 dest[i] = ((uint32_t)src[j]) | (((uint32_t)src[j+1])<<8) |
331 (((uint32_t)src[j+2])<<16) | (((uint32_t)src[j+3])<<24);
332 }
333 }
334
335 CL_NS_END
336