123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- #include "stdafx.h"
- #include "MD5Checksum.h"
- #include "MD5ChecksumDefines.h"
- extern HANDLE g_EventCheckMd5;
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- /*****************************************************************************************
- *****************************************************************************************/
- BYTE CMD5Checksum::GetMD5(LPCTSTR sFilePath, CString &sMd5)
- {
-
- try
- {
- CFile file;
- if(file.Open(sFilePath,CFile::modeRead)==0)
- return 1;
- CMD5Checksum MD5Checksum; //checksum object
- int nLength = 0; //number of bytes read from the file
- const int nBufferSize = 500*1024; //checksum the file in blocks of 1024 bytes
- BYTE Buffer[nBufferSize]; //buffer for data read from the file
- BYTE btRet = 0;
- //checksum the file in blocks of 1024 bytes
- while ((nLength = file.Read( Buffer, nBufferSize )) > 0 )
- {
- if(WaitForSingleObject(g_EventCheckMd5,0) == WAIT_OBJECT_0)
- {
- btRet = 2;
- break;
- }
- MD5Checksum.Update( Buffer, nLength );
- }
- file.Close();
- //finalise the checksum and return it
- sMd5 = MD5Checksum.Final();
- return btRet;
- }
- //report any file exceptions in debug mode only
- catch (CFileException* e )
- {
- TRACE0("CMD5Checksum::GetMD5: CFileException caught");
- throw e;
- }
- return 1;
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::RotateLeft
- DETAILS: private
- DESCRIPTION: Rotates the bits in a 32 bit DWORD left by a specified amount
- RETURNS: The rotated DWORD
- ARGUMENTS: DWORD x : the value to be rotated
- int n : the number of bits to rotate by
- *****************************************************************************************/
- DWORD CMD5Checksum::RotateLeft(DWORD x, int n)
- {
- //check that DWORD is 4 bytes long - true in Visual C++ 6 and 32 bit Windows
- ASSERT( sizeof(x) == 4 );
- //rotate and return x
- return (x << n) | (x >> (32-n));
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::FF
- DETAILS: protected
- DESCRIPTION: Implementation of basic MD5 transformation algorithm
- RETURNS: none
- ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum
- DWORD X : Input data
- DWORD S : MD5_SXX Transformation constant
- DWORD T : MD5_TXX Transformation constant
- NOTES: None
- *****************************************************************************************/
- void CMD5Checksum::FF( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
- {
- DWORD F = (B & C) | (~B & D);
- A += F + X + T;
- A = RotateLeft(A, S);
- A += B;
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::GG
- DETAILS: protected
- DESCRIPTION: Implementation of basic MD5 transformation algorithm
- RETURNS: none
- ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum
- DWORD X : Input data
- DWORD S : MD5_SXX Transformation constant
- DWORD T : MD5_TXX Transformation constant
- NOTES: None
- *****************************************************************************************/
- void CMD5Checksum::GG( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
- {
- DWORD G = (B & D) | (C & ~D);
- A += G + X + T;
- A = RotateLeft(A, S);
- A += B;
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::HH
- DETAILS: protected
- DESCRIPTION: Implementation of basic MD5 transformation algorithm
- RETURNS: none
- ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum
- DWORD X : Input data
- DWORD S : MD5_SXX Transformation constant
- DWORD T : MD5_TXX Transformation constant
- NOTES: None
- *****************************************************************************************/
- void CMD5Checksum::HH( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
- {
- DWORD H = (B ^ C ^ D);
- A += H + X + T;
- A = RotateLeft(A, S);
- A += B;
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::II
- DETAILS: protected
- DESCRIPTION: Implementation of basic MD5 transformation algorithm
- RETURNS: none
- ARGUMENTS: DWORD &A, B, C, D : Current (partial) checksum
- DWORD X : Input data
- DWORD S : MD5_SXX Transformation constant
- DWORD T : MD5_TXX Transformation constant
- NOTES: None
- *****************************************************************************************/
- void CMD5Checksum::II( DWORD& A, DWORD B, DWORD C, DWORD D, DWORD X, DWORD S, DWORD T)
- {
- DWORD I = (C ^ (B | ~D));
- A += I + X + T;
- A = RotateLeft(A, S);
- A += B;
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::ByteToDWord
- DETAILS: private
- DESCRIPTION: Transfers the data in an 8 bit array to a 32 bit array
- RETURNS: void
- ARGUMENTS: DWORD* Output : the 32 bit (unsigned long) destination array
- BYTE* Input : the 8 bit (unsigned char) source array
- UINT nLength : the number of 8 bit data items in the source array
- NOTES: Four BYTES from the input array are transferred to each DWORD entry
- of the output array. The first BYTE is transferred to the bits (0-7)
- of the output DWORD, the second BYTE to bits 8-15 etc.
- The algorithm assumes that the input array is a multiple of 4 bytes long
- so that there is a perfect fit into the array of 32 bit words.
- *****************************************************************************************/
- void CMD5Checksum::ByteToDWord(DWORD* Output, BYTE* Input, UINT nLength)
- {
- //entry invariants
- ASSERT( nLength % 4 == 0 );
- ASSERT( AfxIsValidAddress(Output, nLength/4, TRUE) );
- ASSERT( AfxIsValidAddress(Input, nLength, FALSE) );
- //initialisations
- UINT i=0; //index to Output array
- UINT j=0; //index to Input array
- //transfer the data by shifting and copying
- for ( ; j < nLength; i++, j += 4)
- {
- Output[i] = (ULONG)Input[j] |
- (ULONG)Input[j+1] << 8 |
- (ULONG)Input[j+2] << 16 |
- (ULONG)Input[j+3] << 24;
- }
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::Transform
- DETAILS: protected
- DESCRIPTION: MD5 basic transformation algorithm; transforms 'm_lMD5'
- RETURNS: void
- ARGUMENTS: BYTE Block[64]
- NOTES: An MD5 checksum is calculated by four rounds of 'Transformation'.
- The MD5 checksum currently held in m_lMD5 is merged by the
- transformation process with data passed in 'Block'.
- *****************************************************************************************/
- void CMD5Checksum::Transform(BYTE Block[64])
- {
- //initialise local data with current checksum
- ULONG a = m_lMD5[0];
- ULONG b = m_lMD5[1];
- ULONG c = m_lMD5[2];
- ULONG d = m_lMD5[3];
- //copy BYTES from input 'Block' to an array of ULONGS 'X'
- ULONG X[16];
- ByteToDWord( X, Block, 64 );
- //Perform Round 1 of the transformation
- FF (a, b, c, d, X[ 0], MD5_S11, MD5_T01);
- FF (d, a, b, c, X[ 1], MD5_S12, MD5_T02);
- FF (c, d, a, b, X[ 2], MD5_S13, MD5_T03);
- FF (b, c, d, a, X[ 3], MD5_S14, MD5_T04);
- FF (a, b, c, d, X[ 4], MD5_S11, MD5_T05);
- FF (d, a, b, c, X[ 5], MD5_S12, MD5_T06);
- FF (c, d, a, b, X[ 6], MD5_S13, MD5_T07);
- FF (b, c, d, a, X[ 7], MD5_S14, MD5_T08);
- FF (a, b, c, d, X[ 8], MD5_S11, MD5_T09);
- FF (d, a, b, c, X[ 9], MD5_S12, MD5_T10);
- FF (c, d, a, b, X[10], MD5_S13, MD5_T11);
- FF (b, c, d, a, X[11], MD5_S14, MD5_T12);
- FF (a, b, c, d, X[12], MD5_S11, MD5_T13);
- FF (d, a, b, c, X[13], MD5_S12, MD5_T14);
- FF (c, d, a, b, X[14], MD5_S13, MD5_T15);
- FF (b, c, d, a, X[15], MD5_S14, MD5_T16);
- //Perform Round 2 of the transformation
- GG (a, b, c, d, X[ 1], MD5_S21, MD5_T17);
- GG (d, a, b, c, X[ 6], MD5_S22, MD5_T18);
- GG (c, d, a, b, X[11], MD5_S23, MD5_T19);
- GG (b, c, d, a, X[ 0], MD5_S24, MD5_T20);
- GG (a, b, c, d, X[ 5], MD5_S21, MD5_T21);
- GG (d, a, b, c, X[10], MD5_S22, MD5_T22);
- GG (c, d, a, b, X[15], MD5_S23, MD5_T23);
- GG (b, c, d, a, X[ 4], MD5_S24, MD5_T24);
- GG (a, b, c, d, X[ 9], MD5_S21, MD5_T25);
- GG (d, a, b, c, X[14], MD5_S22, MD5_T26);
- GG (c, d, a, b, X[ 3], MD5_S23, MD5_T27);
- GG (b, c, d, a, X[ 8], MD5_S24, MD5_T28);
- GG (a, b, c, d, X[13], MD5_S21, MD5_T29);
- GG (d, a, b, c, X[ 2], MD5_S22, MD5_T30);
- GG (c, d, a, b, X[ 7], MD5_S23, MD5_T31);
- GG (b, c, d, a, X[12], MD5_S24, MD5_T32);
- //Perform Round 3 of the transformation
- HH (a, b, c, d, X[ 5], MD5_S31, MD5_T33);
- HH (d, a, b, c, X[ 8], MD5_S32, MD5_T34);
- HH (c, d, a, b, X[11], MD5_S33, MD5_T35);
- HH (b, c, d, a, X[14], MD5_S34, MD5_T36);
- HH (a, b, c, d, X[ 1], MD5_S31, MD5_T37);
- HH (d, a, b, c, X[ 4], MD5_S32, MD5_T38);
- HH (c, d, a, b, X[ 7], MD5_S33, MD5_T39);
- HH (b, c, d, a, X[10], MD5_S34, MD5_T40);
- HH (a, b, c, d, X[13], MD5_S31, MD5_T41);
- HH (d, a, b, c, X[ 0], MD5_S32, MD5_T42);
- HH (c, d, a, b, X[ 3], MD5_S33, MD5_T43);
- HH (b, c, d, a, X[ 6], MD5_S34, MD5_T44);
- HH (a, b, c, d, X[ 9], MD5_S31, MD5_T45);
- HH (d, a, b, c, X[12], MD5_S32, MD5_T46);
- HH (c, d, a, b, X[15], MD5_S33, MD5_T47);
- HH (b, c, d, a, X[ 2], MD5_S34, MD5_T48);
- //Perform Round 4 of the transformation
- II (a, b, c, d, X[ 0], MD5_S41, MD5_T49);
- II (d, a, b, c, X[ 7], MD5_S42, MD5_T50);
- II (c, d, a, b, X[14], MD5_S43, MD5_T51);
- II (b, c, d, a, X[ 5], MD5_S44, MD5_T52);
- II (a, b, c, d, X[12], MD5_S41, MD5_T53);
- II (d, a, b, c, X[ 3], MD5_S42, MD5_T54);
- II (c, d, a, b, X[10], MD5_S43, MD5_T55);
- II (b, c, d, a, X[ 1], MD5_S44, MD5_T56);
- II (a, b, c, d, X[ 8], MD5_S41, MD5_T57);
- II (d, a, b, c, X[15], MD5_S42, MD5_T58);
- II (c, d, a, b, X[ 6], MD5_S43, MD5_T59);
- II (b, c, d, a, X[13], MD5_S44, MD5_T60);
- II (a, b, c, d, X[ 4], MD5_S41, MD5_T61);
- II (d, a, b, c, X[11], MD5_S42, MD5_T62);
- II (c, d, a, b, X[ 2], MD5_S43, MD5_T63);
- II (b, c, d, a, X[ 9], MD5_S44, MD5_T64);
- //add the transformed values to the current checksum
- m_lMD5[0] += a;
- m_lMD5[1] += b;
- m_lMD5[2] += c;
- m_lMD5[3] += d;
- }
- /*****************************************************************************************
- CONSTRUCTOR: CMD5Checksum
- DESCRIPTION: Initialises member data
- ARGUMENTS: None
- NOTES: None
- *****************************************************************************************/
- CMD5Checksum::CMD5Checksum()
- {
- // zero members
- memset( m_lpszBuffer, 0, 64 );
- m_nCount[0] = m_nCount[1] = 0;
- // Load magic state initialization constants
- m_lMD5[0] = MD5_INIT_STATE_0;
- m_lMD5[1] = MD5_INIT_STATE_1;
- m_lMD5[2] = MD5_INIT_STATE_2;
- m_lMD5[3] = MD5_INIT_STATE_3;
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::DWordToByte
- DETAILS: private
- DESCRIPTION: Transfers the data in an 32 bit array to a 8 bit array
- RETURNS: void
- ARGUMENTS: BYTE* Output : the 8 bit destination array
- DWORD* Input : the 32 bit source array
- UINT nLength : the number of 8 bit data items in the source array
- NOTES: One DWORD from the input array is transferred into four BYTES
- in the output array. The first (0-7) bits of the first DWORD are
- transferred to the first output BYTE, bits bits 8-15 are transferred from
- the second BYTE etc.
- The algorithm assumes that the output array is a multiple of 4 bytes long
- so that there is a perfect fit of 8 bit BYTES into the 32 bit DWORDs.
- *****************************************************************************************/
- void CMD5Checksum::DWordToByte(BYTE* Output, DWORD* Input, UINT nLength )
- {
- //entry invariants
- ASSERT( nLength % 4 == 0 );
- ASSERT( AfxIsValidAddress(Output, nLength, TRUE) );
- ASSERT( AfxIsValidAddress(Input, nLength/4, FALSE) );
- //transfer the data by shifting and copying
- UINT i = 0;
- UINT j = 0;
- for ( ; j < nLength; i++, j += 4)
- {
- Output[j] = (UCHAR)(Input[i] & 0xff );
- Output[j+1] = (UCHAR)((Input[i] >> 8) & 0xff);
- Output[j+2] = (UCHAR)((Input[i] >> 16) & 0xff);
- Output[j+3] = (UCHAR)((Input[i] >> 24) & 0xff);
- }
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::Final
- DETAILS: protected
- DESCRIPTION: Implementation of main MD5 checksum algorithm; ends the checksum calculation.
- RETURNS: CString : the final hexadecimal MD5 checksum result
- ARGUMENTS: None
- NOTES: Performs the final MD5 checksum calculation ('Update' does most of the work,
- this function just finishes the calculation.)
- *****************************************************************************************/
- CString CMD5Checksum::Final()
- {
- //Save number of bits
- BYTE Bits[8];
- DWordToByte( Bits, m_nCount, 8 );
- //Pad out to 56 mod 64.
- UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3f);
- UINT nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex);
- Update( PADDING, nPadLen );
- //Append length (before padding)
- Update( Bits, 8 );
- //Store final state in 'lpszMD5'
- const int nMD5Size = 16;
- unsigned char lpszMD5[ nMD5Size ];
- DWordToByte( lpszMD5, m_lMD5, nMD5Size );
- //Convert the hexadecimal checksum to a CString
- CString strMD5;
- for ( int i=0; i < nMD5Size; i++)
- {
- CString Str;
- if (lpszMD5[i] == 0)
- {
- Str = CString("00");
- }
- else if (lpszMD5[i] <= 15)
- {
- Str.Format(_T("0%X"),lpszMD5[i]);
- }
- else
- {
- Str.Format(_T("%X"),lpszMD5[i]);
- }
- ASSERT( Str.GetLength() == 2 );
- strMD5 += Str;
- }
- ASSERT( strMD5.GetLength() == 32 );
- /*
- char szMd5[MAX_DESC] = {0};
- sprintf_s(szMd5, sizeof(szMd5), "%s", strMD5.GetBuffer());
- strMD5.ReleaseBuffer();
- return szMd5;
- */
- return strMD5;
- }
- /*****************************************************************************************
- FUNCTION: CMD5Checksum::Update
- DETAILS: protected
- DESCRIPTION: Implementation of main MD5 checksum algorithm
- RETURNS: void
- ARGUMENTS: BYTE* Input : input block
- UINT nInputLen : length of input block
- NOTES: Computes the partial MD5 checksum for 'nInputLen' bytes of data in 'Input'
- *****************************************************************************************/
- void CMD5Checksum::Update( BYTE* Input, ULONG nInputLen )
- {
- //Compute number of bytes mod 64
- UINT nIndex = (UINT)((m_nCount[0] >> 3) & 0x3F);
- //Update number of bits
- if ( ( m_nCount[0] += nInputLen << 3 ) < ( nInputLen << 3) )
- {
- m_nCount[1]++;
- }
- m_nCount[1] += (nInputLen >> 29);
- //Transform as many times as possible.
- UINT i=0;
- UINT nPartLen = 64 - nIndex;
- if (nInputLen >= nPartLen)
- {
- memcpy( &m_lpszBuffer[nIndex], Input, nPartLen );
- Transform( m_lpszBuffer );
- for (i = nPartLen; i + 63 < nInputLen; i += 64)
- {
- Transform( &Input[i] );
- }
- nIndex = 0;
- }
- else
- {
- i = 0;
- }
- // Buffer remaining input
- memcpy( &m_lpszBuffer[nIndex], &Input[i], nInputLen-i);
- }
- CString CMD5Checksum::GetMD5OfString(CString strString)
- {
- try
- {
- CMD5Checksum MD5Checksum; //checksum object
- int nLength = strString.GetLength(); //number of bytes read from the file
- //const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes
- BYTE *Buffer; //buffer for data read from the file
- Buffer=(BYTE*)(strString.GetBuffer(nLength));
- //checksum the file in blocks of 1024 bytes
- //while ((nLength = File.Read( Buffer, nBufferSize )) > 0 )
- //{
- MD5Checksum.Update( Buffer, nLength );
- //}
- //finalise the checksum and return it
- return MD5Checksum.Final();
- }
- //report any file exceptions in debug mode only
- catch (CFileException* e )
- {
- TRACE0("CMD5Checksum::GetMD5: CFileException caught");
- throw e;
- }
- }
|