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