xref: /OK3568_Linux_fs/external/rkupdate/MD5Checksum.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // MD5Checksum.cpp: implementation of the MD5Checksum class.
2 //
3 //////////////////////////////////////////////////////////////////////
4 
5 
6 /****************************************************************************************
7 This software is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
8 Incorporation of this statement is a condition of use; please see the RSA
9 Data Security Inc copyright notice below:-
10 
11 Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
12 rights reserved.
13 
14 RSA Data Security, Inc. makes no representations concerning either
15 the merchantability of this software or the suitability of this
16 software for any particular purpose. It is provided "as is"
17 without express or implied warranty of any kind.
18 
19 These notices must be retained in any copies of any part of this
20 documentation and/or software.
21 
22 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
23 rights reserved.
24 License to copy and use this software is granted provided that it
25 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
26 Algorithm" in all material mentioning or referencing this software
27 or this function.
28 License is also granted to make and use derivative works provided
29 that such works are identified as "derived from the RSA Data
30 Security, Inc. MD5 Message-Digest Algorithm" in all material
31 mentioning or referencing the derived work.
32 RSA Data Security, Inc. makes no representations concerning either
33 the merchantability of this software or the suitability of this
34 software for any particular purpose. It is provided "as is"
35 without express or implied warranty of any kind.
36 
37 These notices must be retained in any copies of any part of this
38 documentation and/or software.
39 *****************************************************************************************/
40 
41 /****************************************************************************************
42 This implementation of the RSA MD5 Algorithm was written by Langfine Ltd
43 (www.langfine.com).
44 
45 Langfine Ltd makes no representations concerning either
46 the merchantability of this software or the suitability of this
47 software for any particular purpose. It is provided "as is"
48 without express or implied warranty of any kind.
49 
50 In addition to the above, Langfine make no warrant or assurances regarding the
51 accuracy of this implementation of the MD5 checksum algorithm nor any assurances regarding
52 its suitability for any purposes.
53 
54 This implementation may be used freely provided that Langfine is credited
55 in a copyright or similar notices (eg, RSA MD5 Algorithm implemented by Langfine
56 Ltd.) and provided that the RSA Data Security notices are complied with.
57 */
58 #include "MD5Checksum.h"
59 #include "MD5ChecksumDefines.h"
60 
61 
62 
63 /*****************************************************************************************
64 FUNCTION:       CMD5Checksum::GetMD5
65 DETAILS:        static, public
66 DESCRIPTION:    Gets the MD5 checksum for a specified file
67 RETURNS:        CString : the hexadecimal MD5 checksum for the specified file
68 ARGUMENTS:      CString& strFilePath : the full pathname of the specified file
69 NOTES:          Provides an interface to the CMD5Checksum class. 'strFilePath' name should
70                 hold the full pathname of the file, eg C:\My Documents\Arcticle.txt.
71                 NB. If any problems occur with opening or reading this file, a CFileException
72                 will be thrown; callers of this function should be ready to catch this
73                 exception.
74 *****************************************************************************************/
GetMD5(const tstring & strFilePath,long long nLength)75 tstring CMD5Checksum::GetMD5(const tstring &strFilePath, long long nLength)
76 {
77     //open the file as a binary file in readonly mode, denying write access
78     FILE *file = NULL;
79     file = fopen(strFilePath.c_str(), _T("rb"));
80     if (!file)
81     {
82         return _T("");
83     }
84     //the file has been successfully opened, so now get and return its checksum
85     tstring strRet;
86     strRet = GetMD5(file, nLength);
87     fclose(file);
88     return strRet;
89 }
90 
_GetMD5(const tstring & strFilePath,long long nLength)91 unsigned char *CMD5Checksum::_GetMD5(const tstring &strFilePath, long long nLength)
92 {
93     //open the file as a binary file in readonly mode, denying write access
94     FILE *file = NULL;
95     file = fopen(strFilePath.c_str(), _T("rb"));
96     if (!file)
97     {
98         return NULL;
99     }
100 
101     //the file has been successfully opened, so now get and return its checksum
102     unsigned char *pRet;
103     pRet = _GetMD5(file, nLength);
104     fclose(file);
105     return pRet;
106 }
107 
108 /*****************************************************************************************
109 FUNCTION:       CMD5Checksum::GetMD5
110 DETAILS:        static, public
111 DESCRIPTION:    Gets the MD5 checksum for a specified file
112 RETURNS:        CString : the hexadecimal MD5 checksum for the specified file
113 ARGUMENTS:      CFile& File : the specified file
114 NOTES:          Provides an interface to the CMD5Checksum class. 'File' should be open in
115                 binary readonly mode before calling this function.
116                 NB. Callers of this function should be ready to catch any CFileException
117                 thrown by the CFile functions
118 *****************************************************************************************/
GetMD5(FILE * File,long long nLength)119 tstring CMD5Checksum::GetMD5(FILE *File, long long nLength)
120 {
121     try
122     {
123         CMD5Checksum MD5Checksum;       //checksum object
124         int nCount = 0;             //number of bytes read from the file
125         const int nBufferSize = 1024;   //checksum the file in blocks of 1024 bytes
126         BYTE Buffer[nBufferSize];       //buffer for data read from the file
127 
128         long long uiFileSize = nLength;
129         //fseeko(File,0,SEEK_END);
130         //uiFileSize = ftello(File);
131         fseeko(File, 0, SEEK_SET);
132         //checksum the file in blocks of 1024 bytes
133         while (uiFileSize > 0)
134         {
135             nCount = (uiFileSize >= nBufferSize) ? nBufferSize : uiFileSize;
136             nCount = fread(Buffer, 1, nCount, File);
137             uiFileSize -= nCount;
138             MD5Checksum.Update(Buffer, nCount);
139         }
140         //finalise the checksum and return it
141         return MD5Checksum.Final();
142     }
143 
144     //report any file exceptions in debug mode only
145     catch (...)
146     {
147         return _T("");
148     }
149 }
150 
_GetMD5(FILE * File,long long nLength)151 unsigned char *CMD5Checksum::_GetMD5(FILE *File, long long nLength)
152 {
153     try
154     {
155         CMD5Checksum MD5Checksum;       //checksum object
156         int nCount = 0;             //number of bytes read from the file
157         const int nBufferSize = 1024;   //checksum the file in blocks of 1024 bytes
158         BYTE Buffer[nBufferSize];       //buffer for data read from the file
159 
160         long long uiFileSize = nLength;
161         //      fseeko(File,0,SEEK_END);
162         //      uiFileSize = ftello(File);
163         fseeko(File, 0, SEEK_SET);
164         //checksum the file in blocks of 1024 bytes
165         while (uiFileSize > 0)
166         {
167             nCount = (uiFileSize >= nBufferSize) ? nBufferSize : uiFileSize;
168             nCount = fread(Buffer, 1, nCount, File);
169             uiFileSize -= nCount;
170             MD5Checksum.Update(Buffer, nCount);
171         }
172 
173         //finalise the checksum and return it
174         return MD5Checksum.FinalChar();
175     }
176 
177     //report any file exceptions in debug mode only
178     catch (...)
179     {
180         return NULL;
181     }
182 }
183 
184 /*****************************************************************************************
185 FUNCTION:       CMD5Checksum::GetMD5
186 DETAILS:        static, public
187 DESCRIPTION:    Gets the MD5 checksum for data in a BYTE array
188 RETURNS:        CString : the hexadecimal MD5 checksum for the specified data
189 ARGUMENTS:      BYTE* pBuf  :   pointer to the BYTE array
190                 UINT nLength :  number of BYTEs of data to be checksumed
191 NOTES:          Provides an interface to the CMD5Checksum class. Any data that can
192                 be cast to a BYTE array of known length can be checksummed by this
193                 function. Typically, CString and char arrays will be checksumed,
194                 although this function can be used to check the integrity of any BYTE array.
195                 A buffer of zero length can be checksummed; all buffers of zero length
196                 will return the same checksum.
197 *****************************************************************************************/
GetMD5(BYTE * pBuf,UINT nLength)198 tstring CMD5Checksum::GetMD5(BYTE *pBuf, UINT nLength)
199 {
200 
201     //calculate and return the checksum
202     CMD5Checksum MD5Checksum;
203     MD5Checksum.Update(pBuf, nLength);
204     return MD5Checksum.Final();
205 }
206 
_GetMD5(BYTE * pBuf,UINT nLength)207 unsigned char   *CMD5Checksum::_GetMD5(BYTE *pBuf, UINT nLength)
208 {
209     //calculate and return the checksum
210     CMD5Checksum MD5Checksum;
211     MD5Checksum.Update(pBuf, nLength);
212     return MD5Checksum.FinalChar();
213 }
214 
215 /*****************************************************************************************
216 FUNCTION:       CMD5Checksum::RotateLeft
217 DETAILS:        private
218 DESCRIPTION:    Rotates the bits in a 32 bit DWORD left by a specified amount
219 RETURNS:        The rotated DWORD
220 ARGUMENTS:      DWORD x : the value to be rotated
221                 int n   : the number of bits to rotate by
222 *****************************************************************************************/
RotateLeft(DWORD x,int n)223 DWORD CMD5Checksum::RotateLeft(DWORD x, int n)
224 {
225     //check that DWORD is 4 bytes long - true in Visual C++ 6 and 32 bit Windows
226     assert(sizeof(x) == 4);
227 
228     //rotate and return x
229     return (x << n) | (x >> (32 - n));
230 }
231 
232 
233 /*****************************************************************************************
234 FUNCTION:       CMD5Checksum::FF
235 DETAILS:        protected
236 DESCRIPTION:    Implementation of basic MD5 transformation algorithm
237 RETURNS:        none
238 ARGUMENTS:      DWORD &A, B, C, D : Current (partial) checksum
239                 DWORD X           : Input data
240                 DWORD S           : MD5_SXX Transformation constant
241                 DWORD T           : MD5_TXX Transformation constant
242 NOTES:          None
243 *****************************************************************************************/
FF(DWORD & A,DWORD B,DWORD C,DWORD D,DWORD X,DWORD S,DWORD T)244 void CMD5Checksum::FF(DWORD &A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
245 {
246     DWORD F = (B & C) | (~B & D);
247     A += F + X + T;
248     A = RotateLeft(A, S);
249     A += B;
250 }
251 
252 
253 /*****************************************************************************************
254 FUNCTION:       CMD5Checksum::GG
255 DETAILS:        protected
256 DESCRIPTION:    Implementation of basic MD5 transformation algorithm
257 RETURNS:        none
258 ARGUMENTS:      DWORD &A, B, C, D : Current (partial) checksum
259                 DWORD X           : Input data
260                 DWORD S           : MD5_SXX Transformation constant
261                 DWORD T           : MD5_TXX Transformation constant
262 NOTES:          None
263 *****************************************************************************************/
GG(DWORD & A,DWORD B,DWORD C,DWORD D,DWORD X,DWORD S,DWORD T)264 void CMD5Checksum::GG(DWORD &A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
265 {
266     DWORD G = (B & D) | (C & ~D);
267     A += G + X + T;
268     A = RotateLeft(A, S);
269     A += B;
270 }
271 
272 
273 /*****************************************************************************************
274 FUNCTION:       CMD5Checksum::HH
275 DETAILS:        protected
276 DESCRIPTION:    Implementation of basic MD5 transformation algorithm
277 RETURNS:        none
278 ARGUMENTS:      DWORD &A, B, C, D : Current (partial) checksum
279                 DWORD X           : Input data
280                 DWORD S           : MD5_SXX Transformation constant
281                 DWORD T           : MD5_TXX Transformation constant
282 NOTES:          None
283 *****************************************************************************************/
HH(DWORD & A,DWORD B,DWORD C,DWORD D,DWORD X,DWORD S,DWORD T)284 void CMD5Checksum::HH(DWORD &A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
285 {
286     DWORD H = (B ^ C ^ D);
287     A += H + X + T;
288     A = RotateLeft(A, S);
289     A += B;
290 }
291 
292 
293 /*****************************************************************************************
294 FUNCTION:       CMD5Checksum::II
295 DETAILS:        protected
296 DESCRIPTION:    Implementation of basic MD5 transformation algorithm
297 RETURNS:        none
298 ARGUMENTS:      DWORD &A, B, C, D : Current (partial) checksum
299                 DWORD X           : Input data
300                 DWORD S           : MD5_SXX Transformation constant
301                 DWORD T           : MD5_TXX Transformation constant
302 NOTES:          None
303 *****************************************************************************************/
II(DWORD & A,DWORD B,DWORD C,DWORD D,DWORD X,DWORD S,DWORD T)304 void CMD5Checksum::II(DWORD &A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
305 {
306     DWORD I = (C ^ (B | ~D));
307     A += I + X + T;
308     A = RotateLeft(A, S);
309     A += B;
310 }
311 
312 
313 /*****************************************************************************************
314 FUNCTION:       CMD5Checksum::ByteToDWord
315 DETAILS:        private
316 DESCRIPTION:    Transfers the data in an 8 bit array to a 32 bit array
317 RETURNS:        void
318 ARGUMENTS:      DWORD* Output : the 32 bit (unsigned long) destination array
319                 BYTE* Input   : the 8 bit (unsigned char) source array
320                 UINT nLength  : the number of 8 bit data items in the source array
321 NOTES:          Four BYTES from the input array are transferred to each DWORD entry
322                 of the output array. The first BYTE is transferred to the bits (0-7)
323                 of the output DWORD, the second BYTE to bits 8-15 etc.
324                 The algorithm assumes that the input array is a multiple of 4 bytes long
325                 so that there is a perfect fit into the array of 32 bit words.
326 *****************************************************************************************/
ByteToDWord(DWORD * Output,BYTE * Input,UINT nLength)327 void CMD5Checksum::ByteToDWord(DWORD *Output, BYTE *Input, UINT nLength)
328 {
329 
330     //initialisations
331     UINT i = 0; //index to Output array
332     UINT j = 0; //index to Input array
333 
334     //transfer the data by shifting and copying
335     for (; j < nLength; i++, j += 4)
336     {
337         Output[i] = (UINT)Input[j]          |
338                     (UINT)Input[j + 1] << 8   |
339                     (UINT)Input[j + 2] << 16 |
340                     (UINT)Input[j + 3] << 24;
341     }
342 }
343 
344 /*****************************************************************************************
345 FUNCTION:       CMD5Checksum::Transform
346 DETAILS:        protected
347 DESCRIPTION:    MD5 basic transformation algorithm;  transforms 'm_lMD5'
348 RETURNS:        void
349 ARGUMENTS:      BYTE Block[64]
350 NOTES:          An MD5 checksum is calculated by four rounds of 'Transformation'.
351                 The MD5 checksum currently held in m_lMD5 is merged by the
352                 transformation process with data passed in 'Block'.
353 *****************************************************************************************/
Transform(BYTE Block[64])354 void CMD5Checksum::Transform(BYTE Block[64])
355 {
356     //initialise local data with current checksum
357     UINT a = m_lMD5[0];
358     UINT b = m_lMD5[1];
359     UINT c = m_lMD5[2];
360     UINT d = m_lMD5[3];
361 
362     //copy BYTES from input 'Block' to an array of UINTS 'X'
363     UINT X[16];
364     ByteToDWord(X, Block, 64);
365 
366     //Perform Round 1 of the transformation
367     FF(a, b, c, d, X[ 0], MD5_S11, MD5_T01);
368     FF(d, a, b, c, X[ 1], MD5_S12, MD5_T02);
369     FF(c, d, a, b, X[ 2], MD5_S13, MD5_T03);
370     FF(b, c, d, a, X[ 3], MD5_S14, MD5_T04);
371     FF(a, b, c, d, X[ 4], MD5_S11, MD5_T05);
372     FF(d, a, b, c, X[ 5], MD5_S12, MD5_T06);
373     FF(c, d, a, b, X[ 6], MD5_S13, MD5_T07);
374     FF(b, c, d, a, X[ 7], MD5_S14, MD5_T08);
375     FF(a, b, c, d, X[ 8], MD5_S11, MD5_T09);
376     FF(d, a, b, c, X[ 9], MD5_S12, MD5_T10);
377     FF(c, d, a, b, X[10], MD5_S13, MD5_T11);
378     FF(b, c, d, a, X[11], MD5_S14, MD5_T12);
379     FF(a, b, c, d, X[12], MD5_S11, MD5_T13);
380     FF(d, a, b, c, X[13], MD5_S12, MD5_T14);
381     FF(c, d, a, b, X[14], MD5_S13, MD5_T15);
382     FF(b, c, d, a, X[15], MD5_S14, MD5_T16);
383 
384     //Perform Round 2 of the transformation
385     GG(a, b, c, d, X[ 1], MD5_S21, MD5_T17);
386     GG(d, a, b, c, X[ 6], MD5_S22, MD5_T18);
387     GG(c, d, a, b, X[11], MD5_S23, MD5_T19);
388     GG(b, c, d, a, X[ 0], MD5_S24, MD5_T20);
389     GG(a, b, c, d, X[ 5], MD5_S21, MD5_T21);
390     GG(d, a, b, c, X[10], MD5_S22, MD5_T22);
391     GG(c, d, a, b, X[15], MD5_S23, MD5_T23);
392     GG(b, c, d, a, X[ 4], MD5_S24, MD5_T24);
393     GG(a, b, c, d, X[ 9], MD5_S21, MD5_T25);
394     GG(d, a, b, c, X[14], MD5_S22, MD5_T26);
395     GG(c, d, a, b, X[ 3], MD5_S23, MD5_T27);
396     GG(b, c, d, a, X[ 8], MD5_S24, MD5_T28);
397     GG(a, b, c, d, X[13], MD5_S21, MD5_T29);
398     GG(d, a, b, c, X[ 2], MD5_S22, MD5_T30);
399     GG(c, d, a, b, X[ 7], MD5_S23, MD5_T31);
400     GG(b, c, d, a, X[12], MD5_S24, MD5_T32);
401 
402     //Perform Round 3 of the transformation
403     HH(a, b, c, d, X[ 5], MD5_S31, MD5_T33);
404     HH(d, a, b, c, X[ 8], MD5_S32, MD5_T34);
405     HH(c, d, a, b, X[11], MD5_S33, MD5_T35);
406     HH(b, c, d, a, X[14], MD5_S34, MD5_T36);
407     HH(a, b, c, d, X[ 1], MD5_S31, MD5_T37);
408     HH(d, a, b, c, X[ 4], MD5_S32, MD5_T38);
409     HH(c, d, a, b, X[ 7], MD5_S33, MD5_T39);
410     HH(b, c, d, a, X[10], MD5_S34, MD5_T40);
411     HH(a, b, c, d, X[13], MD5_S31, MD5_T41);
412     HH(d, a, b, c, X[ 0], MD5_S32, MD5_T42);
413     HH(c, d, a, b, X[ 3], MD5_S33, MD5_T43);
414     HH(b, c, d, a, X[ 6], MD5_S34, MD5_T44);
415     HH(a, b, c, d, X[ 9], MD5_S31, MD5_T45);
416     HH(d, a, b, c, X[12], MD5_S32, MD5_T46);
417     HH(c, d, a, b, X[15], MD5_S33, MD5_T47);
418     HH(b, c, d, a, X[ 2], MD5_S34, MD5_T48);
419 
420     //Perform Round 4 of the transformation
421     II(a, b, c, d, X[ 0], MD5_S41, MD5_T49);
422     II(d, a, b, c, X[ 7], MD5_S42, MD5_T50);
423     II(c, d, a, b, X[14], MD5_S43, MD5_T51);
424     II(b, c, d, a, X[ 5], MD5_S44, MD5_T52);
425     II(a, b, c, d, X[12], MD5_S41, MD5_T53);
426     II(d, a, b, c, X[ 3], MD5_S42, MD5_T54);
427     II(c, d, a, b, X[10], MD5_S43, MD5_T55);
428     II(b, c, d, a, X[ 1], MD5_S44, MD5_T56);
429     II(a, b, c, d, X[ 8], MD5_S41, MD5_T57);
430     II(d, a, b, c, X[15], MD5_S42, MD5_T58);
431     II(c, d, a, b, X[ 6], MD5_S43, MD5_T59);
432     II(b, c, d, a, X[13], MD5_S44, MD5_T60);
433     II(a, b, c, d, X[ 4], MD5_S41, MD5_T61);
434     II(d, a, b, c, X[11], MD5_S42, MD5_T62);
435     II(c, d, a, b, X[ 2], MD5_S43, MD5_T63);
436     II(b, c, d, a, X[ 9], MD5_S44, MD5_T64);
437 
438     //add the transformed values to the current checksum
439     m_lMD5[0] += a;
440     m_lMD5[1] += b;
441     m_lMD5[2] += c;
442     m_lMD5[3] += d;
443 }
444 
445 
446 /*****************************************************************************************
447 CONSTRUCTOR:    CMD5Checksum
448 DESCRIPTION:    Initialises member data
449 ARGUMENTS:      None
450 NOTES:          None
451 *****************************************************************************************/
CMD5Checksum()452 CMD5Checksum::CMD5Checksum()
453 {
454     // zero members
455     memset(m_lpszBuffer, 0, 64);
456     m_nCount[0] = m_nCount[1] = 0;
457     m_pBuffer = NULL;
458     // Load magic state initialization constants
459     m_lMD5[0] = MD5_INIT_STATE_0;
460     m_lMD5[1] = MD5_INIT_STATE_1;
461     m_lMD5[2] = MD5_INIT_STATE_2;
462     m_lMD5[3] = MD5_INIT_STATE_3;
463     m_pBuffer = NULL;
464 }
465 
466 /*****************************************************************************************
467 FUNCTION:       CMD5Checksum::DWordToByte
468 DETAILS:        private
469 DESCRIPTION:    Transfers the data in an 32 bit array to a 8 bit array
470 RETURNS:        void
471 ARGUMENTS:      BYTE* Output  : the 8 bit destination array
472                 DWORD* Input  : the 32 bit source array
473                 UINT nLength  : the number of 8 bit data items in the source array
474 NOTES:          One DWORD from the input array is transferred into four BYTES
475                 in the output array. The first (0-7) bits of the first DWORD are
476                 transferred to the first output BYTE, bits bits 8-15 are transferred from
477                 the second BYTE etc.
478 
479                 The algorithm assumes that the output array is a multiple of 4 bytes long
480                 so that there is a perfect fit of 8 bit BYTES into the 32 bit DWORDs.
481 *****************************************************************************************/
DWordToByte(BYTE * Output,DWORD * Input,UINT nLength)482 void CMD5Checksum::DWordToByte(BYTE *Output, DWORD *Input, UINT nLength)
483 {
484     //transfer the data by shifting and copying
485     UINT i = 0;
486     UINT j = 0;
487     for (; j < nLength; i++, j += 4)
488     {
489         Output[j] = (UCHAR)(Input[i] & 0xff);
490         Output[j + 1] = (UCHAR)((Input[i] >> 8) & 0xff);
491         Output[j + 2] = (UCHAR)((Input[i] >> 16) & 0xff);
492         Output[j + 3] = (UCHAR)((Input[i] >> 24) & 0xff);
493     }
494 }
495 
496 
497 /*****************************************************************************************
498 FUNCTION:       CMD5Checksum::Final
499 DETAILS:        protected
500 DESCRIPTION:    Implementation of main MD5 checksum algorithm; ends the checksum calculation.
501 RETURNS:        CString : the final hexadecimal MD5 checksum result
502 ARGUMENTS:      None
503 NOTES:          Performs the final MD5 checksum calculation ('Update' does most of the work,
504                 this function just finishes the calculation.)
505 *****************************************************************************************/
Final()506 tstring CMD5Checksum::Final()
507 {
508     //Save number of bits
509     BYTE Bits[8];
510     DWordToByte(Bits, m_nCount, 8);
511 
512     //Pad out to 56 mod 64.
513     UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3f);
514     UINT nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex);
515     Update(PADDING, nPadLen);
516 
517     //Append length (before padding)
518     Update(Bits, 8);
519 
520     //Store final state in 'lpszMD5'
521     const int nMD5Size = 16;
522     unsigned char lpszMD5[ nMD5Size ];
523     DWordToByte(lpszMD5, m_lMD5, nMD5Size);
524 
525     //Convert the hexadecimal checksum to a CString
526     tstring strMD5;
527     tchar str[10];
528     strMD5 = _T("");
529     for (int i = 0; i < nMD5Size; i++)
530     {
531         if (lpszMD5[i] == 0)
532         {
533             _tcscpy(str, _T("00"));
534         }
535         else if (lpszMD5[i] <= 15)
536         {
537             _stprintf(str, _T("0%x"), lpszMD5[i]);
538         }
539         else
540         {
541             _stprintf(str, _T("%x"), lpszMD5[i]);
542         }
543 
544         assert(_tcslen(str) == 2);
545         strMD5 += str;
546     }
547     assert(strMD5.size() == 32);
548     return strMD5;
549 }
550 
551 /*****************************************************************************************
552 FUNCTION:       CMD5Checksum::Final
553 DETAILS:        protected
554 DESCRIPTION:    Implementation of main MD5 checksum algorithm; ends the checksum calculation.
555 RETURNS:        CString : the final hexadecimal MD5 checksum result
556 ARGUMENTS:      None
557 NOTES:          Performs the final MD5 checksum calculation ('Update' does most of the work,
558                 this function just finishes the calculation.)
559 *****************************************************************************************/
FinalChar()560 unsigned char *CMD5Checksum::FinalChar()
561 {
562     //Save number of bits
563     BYTE Bits[8];
564     DWordToByte(Bits, m_nCount, 8);
565 
566     //Pad out to 56 mod 64.
567     UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3f);
568     UINT nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex);
569     Update(PADDING, nPadLen);
570 
571     //Append length (before padding)
572     Update(Bits, 8);
573 
574     //Store final state in 'lpszMD5'
575     const int nMD5Size = 16;
576     if (m_pBuffer)
577     {
578         delete []m_pBuffer;
579         m_pBuffer = NULL;
580     }
581     m_pBuffer = new BYTE[nMD5Size];
582     DWordToByte(m_pBuffer, m_lMD5, nMD5Size);
583     return m_pBuffer;
584     //  unsigned char lpszMD5[ nMD5Size ];
585     //  DWordToByte( lpszMD5, m_lMD5, nMD5Size );
586 
587     //  return lpszMD5;
588 }
589 
590 /*****************************************************************************************
591 FUNCTION:       CMD5Checksum::Update
592 DETAILS:        protected
593 DESCRIPTION:    Implementation of main MD5 checksum algorithm
594 RETURNS:        void
595 ARGUMENTS:      BYTE* Input    : input block
596                 UINT nInputLen : length of input block
597 NOTES:          Computes the partial MD5 checksum for 'nInputLen' bytes of data in 'Input'
598 *****************************************************************************************/
Update(BYTE * Input,UINT nInputLen)599 void CMD5Checksum::Update(BYTE *Input,  UINT nInputLen)
600 {
601     //Compute number of bytes mod 64
602     UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3F);
603 
604     //Update number of bits
605     if ((m_nCount[0] += nInputLen << 3)  < (nInputLen << 3))
606     {
607         m_nCount[1]++;
608     }
609     m_nCount[1] += (nInputLen >> 29);
610 
611     //Transform as many times as possible.
612     UINT i = 0;
613     UINT nPartLen = 64 - nIndex;
614     if (nInputLen >= nPartLen)
615     {
616         memcpy(&m_lpszBuffer[nIndex], Input, nPartLen);
617         Transform(m_lpszBuffer);
618         for (i = nPartLen; i + 63 < nInputLen; i += 64)
619         {
620             Transform(&Input[i]);
621         }
622         nIndex = 0;
623     }
624     else
625     {
626         i = 0;
627     }
628 
629     // Buffer remaining input
630     memcpy(&m_lpszBuffer[nIndex], &Input[i], nInputLen - i);
631 }
632 
633 
634