631 lines
22 KiB
C++
Executable File
631 lines
22 KiB
C++
Executable File
// MD5Checksum.cpp: implementation of the MD5Checksum class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/****************************************************************************************
|
|
This software is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
|
|
Incorporation of this statement is a condition of use; please see the RSA
|
|
Data Security Inc copyright notice below:-
|
|
|
|
Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
|
|
rights reserved.
|
|
|
|
RSA Data Security, Inc. makes no representations concerning either
|
|
the merchantability of this software or the suitability of this
|
|
software for any particular purpose. It is provided "as is"
|
|
without express or implied warranty of any kind.
|
|
|
|
These notices must be retained in any copies of any part of this
|
|
documentation and/or software.
|
|
|
|
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
|
rights reserved.
|
|
License to copy and use this software is granted provided that it
|
|
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
|
Algorithm" in all material mentioning or referencing this software
|
|
or this function.
|
|
License is also granted to make and use derivative works provided
|
|
that such works are identified as "derived from the RSA Data
|
|
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
|
mentioning or referencing the derived work.
|
|
RSA Data Security, Inc. makes no representations concerning either
|
|
the merchantability of this software or the suitability of this
|
|
software for any particular purpose. It is provided "as is"
|
|
without express or implied warranty of any kind.
|
|
|
|
These notices must be retained in any copies of any part of this
|
|
documentation and/or software.
|
|
*****************************************************************************************/
|
|
|
|
/****************************************************************************************
|
|
This implementation of the RSA MD5 Algorithm was written by Langfine Ltd
|
|
(www.langfine.com).
|
|
|
|
Langfine Ltd makes no representations concerning either
|
|
the merchantability of this software or the suitability of this
|
|
software for any particular purpose. It is provided "as is"
|
|
without express or implied warranty of any kind.
|
|
|
|
In addition to the above, Langfine make no warrant or assurances regarding the
|
|
accuracy of this implementation of the MD5 checksum algorithm nor any assurances regarding
|
|
its suitability for any purposes.
|
|
|
|
This implementation may be used freely provided that Langfine is credited
|
|
in a copyright or similar notices (eg, RSA MD5 Algorithm implemented by Langfine
|
|
Ltd.) and provided that the RSA Data Security notices are complied with.
|
|
*/
|
|
#include "rkupdate/MD5Checksum.h"
|
|
#include "rkupdate/MD5ChecksumDefines.h"
|
|
|
|
|
|
|
|
/*****************************************************************************************
|
|
FUNCTION: CMD5Checksum::GetMD5
|
|
DETAILS: static, public
|
|
DESCRIPTION: Gets the MD5 checksum for a specified file
|
|
RETURNS: CString : the hexadecimal MD5 checksum for the specified file
|
|
ARGUMENTS: CString& strFilePath : the full pathname of the specified file
|
|
NOTES: Provides an interface to the CMD5Checksum class. 'strFilePath' name should
|
|
hold the full pathname of the file, eg C:\My Documents\Arcticle.txt.
|
|
NB. If any problems occur with opening or reading this file, a CFileException
|
|
will be thrown; callers of this function should be ready to catch this
|
|
exception.
|
|
*****************************************************************************************/
|
|
tstring CMD5Checksum::GetMD5(const tstring& strFilePath,long long nLength)
|
|
{
|
|
//open the file as a binary file in readonly mode, denying write access
|
|
FILE *file=NULL;
|
|
file = fopen(strFilePath.c_str(),_T("rb"));
|
|
if (!file)
|
|
return _T("");
|
|
//the file has been successfully opened, so now get and return its checksum
|
|
tstring strRet;
|
|
strRet = GetMD5(file,nLength);
|
|
fclose(file);
|
|
return strRet;
|
|
}
|
|
|
|
unsigned char * CMD5Checksum::_GetMD5(const tstring& strFilePath,long long nLength)
|
|
{
|
|
//open the file as a binary file in readonly mode, denying write access
|
|
FILE *file=NULL;
|
|
file = fopen(strFilePath.c_str(),_T("rb"));
|
|
if (!file)
|
|
return NULL;
|
|
|
|
//the file has been successfully opened, so now get and return its checksum
|
|
unsigned char *pRet;
|
|
pRet= _GetMD5(file,nLength);
|
|
fclose(file);
|
|
return pRet;
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
FUNCTION: CMD5Checksum::GetMD5
|
|
DETAILS: static, public
|
|
DESCRIPTION: Gets the MD5 checksum for a specified file
|
|
RETURNS: CString : the hexadecimal MD5 checksum for the specified file
|
|
ARGUMENTS: CFile& File : the specified file
|
|
NOTES: Provides an interface to the CMD5Checksum class. 'File' should be open in
|
|
binary readonly mode before calling this function.
|
|
NB. Callers of this function should be ready to catch any CFileException
|
|
thrown by the CFile functions
|
|
*****************************************************************************************/
|
|
tstring CMD5Checksum::GetMD5(FILE *File,long long nLength)
|
|
{
|
|
//try
|
|
//{
|
|
CMD5Checksum MD5Checksum; //checksum object
|
|
int nCount = 0; //number of bytes read from the file
|
|
const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes
|
|
BYTE Buffer[nBufferSize]; //buffer for data read from the file
|
|
|
|
long long uiFileSize=nLength;
|
|
//fseeko(File,0,SEEK_END);
|
|
//uiFileSize = ftello(File);
|
|
fseeko(File,0,SEEK_SET);
|
|
//checksum the file in blocks of 1024 bytes
|
|
while ( uiFileSize>0 )
|
|
{
|
|
nCount = (uiFileSize>=nBufferSize)?nBufferSize:uiFileSize;
|
|
nCount= fread(Buffer,1,nCount,File);
|
|
uiFileSize -= nCount;
|
|
MD5Checksum.Update( Buffer, nCount);
|
|
}
|
|
//finalise the checksum and return it
|
|
return MD5Checksum.Final();
|
|
//}
|
|
|
|
//report any file exceptions in debug mode only
|
|
#if 0
|
|
catch (... )
|
|
{
|
|
return _T("");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
unsigned char * CMD5Checksum::_GetMD5(FILE *File,long long nLength)
|
|
{
|
|
//try
|
|
//{
|
|
CMD5Checksum MD5Checksum; //checksum object
|
|
int nCount = 0; //number of bytes read from the file
|
|
const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes
|
|
BYTE Buffer[nBufferSize]; //buffer for data read from the file
|
|
|
|
long long uiFileSize=nLength;
|
|
// fseeko(File,0,SEEK_END);
|
|
// uiFileSize = ftello(File);
|
|
fseeko(File,0,SEEK_SET);
|
|
//checksum the file in blocks of 1024 bytes
|
|
while ( uiFileSize>0 )
|
|
{
|
|
nCount = (uiFileSize>=nBufferSize)?nBufferSize:uiFileSize;
|
|
nCount= fread(Buffer,1,nCount,File);
|
|
uiFileSize -= nCount;
|
|
MD5Checksum.Update( Buffer, nCount);
|
|
}
|
|
|
|
//finalise the checksum and return it
|
|
return MD5Checksum.FinalChar();
|
|
//}
|
|
|
|
//report any file exceptions in debug mode only
|
|
#if 0
|
|
catch (...)
|
|
{
|
|
return NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
FUNCTION: CMD5Checksum::GetMD5
|
|
DETAILS: static, public
|
|
DESCRIPTION: Gets the MD5 checksum for data in a BYTE array
|
|
RETURNS: CString : the hexadecimal MD5 checksum for the specified data
|
|
ARGUMENTS: BYTE* pBuf : pointer to the BYTE array
|
|
UINT nLength : number of BYTEs of data to be checksumed
|
|
NOTES: Provides an interface to the CMD5Checksum class. Any data that can
|
|
be cast to a BYTE array of known length can be checksummed by this
|
|
function. Typically, CString and char arrays will be checksumed,
|
|
although this function can be used to check the integrity of any BYTE array.
|
|
A buffer of zero length can be checksummed; all buffers of zero length
|
|
will return the same checksum.
|
|
*****************************************************************************************/
|
|
tstring CMD5Checksum::GetMD5(BYTE* pBuf, UINT nLength)
|
|
{
|
|
|
|
//calculate and return the checksum
|
|
CMD5Checksum MD5Checksum;
|
|
MD5Checksum.Update( pBuf, nLength );
|
|
return MD5Checksum.Final();
|
|
}
|
|
|
|
unsigned char * CMD5Checksum::_GetMD5(BYTE* pBuf, UINT nLength)
|
|
{
|
|
//calculate and return the checksum
|
|
CMD5Checksum MD5Checksum;
|
|
MD5Checksum.Update( pBuf, nLength );
|
|
return MD5Checksum.FinalChar();
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
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)
|
|
{
|
|
|
|
//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] = (UINT)Input[j] |
|
|
(UINT)Input[j+1] << 8 |
|
|
(UINT)Input[j+2] << 16 |
|
|
(UINT)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
|
|
UINT a = m_lMD5[0];
|
|
UINT b = m_lMD5[1];
|
|
UINT c = m_lMD5[2];
|
|
UINT d = m_lMD5[3];
|
|
|
|
//copy BYTES from input 'Block' to an array of UINTS 'X'
|
|
UINT 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;
|
|
m_pBuffer = NULL;
|
|
// 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;
|
|
m_pBuffer = NULL;
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
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 )
|
|
{
|
|
//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.)
|
|
*****************************************************************************************/
|
|
tstring 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
|
|
tstring strMD5;
|
|
tchar str[10];
|
|
strMD5=_T("");
|
|
for ( int i=0; i < nMD5Size; i++)
|
|
{
|
|
if (lpszMD5[i] == 0) {
|
|
_tcscpy(str,_T("00"));
|
|
}
|
|
else if (lpszMD5[i] <= 15) {
|
|
_stprintf(str,_T("0%x"),lpszMD5[i]);
|
|
}
|
|
else {
|
|
_stprintf(str,_T("%x"),lpszMD5[i]);
|
|
}
|
|
|
|
assert( _tcslen(str)== 2 );
|
|
strMD5 += str;
|
|
}
|
|
assert( strMD5.size()== 32 );
|
|
return strMD5;
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
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.)
|
|
*****************************************************************************************/
|
|
unsigned char * CMD5Checksum::FinalChar()
|
|
{
|
|
//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;
|
|
if (m_pBuffer)
|
|
{
|
|
delete []m_pBuffer;
|
|
m_pBuffer = NULL;
|
|
}
|
|
m_pBuffer = new BYTE[nMD5Size];
|
|
DWordToByte( m_pBuffer, m_lMD5, nMD5Size );
|
|
return m_pBuffer;
|
|
// unsigned char lpszMD5[ nMD5Size ];
|
|
// DWordToByte( lpszMD5, m_lMD5, nMD5Size );
|
|
|
|
// return lpszMD5;
|
|
}
|
|
|
|
/*****************************************************************************************
|
|
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, UINT 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);
|
|
}
|
|
|
|
|