487 lines
13 KiB
C++
487 lines
13 KiB
C++
// Md5.cpp: implementation of the CMd5 class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "Md5.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[]=__FILE__;
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
|
|
#define FF(a, b, c, d, x, s, ac) { \
|
|
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
|
(a) = ROTATE_LEFT ((a), (s)); \
|
|
(a) += (b); \
|
|
}
|
|
|
|
#define GG(a, b, c, d, x, s, ac) { \
|
|
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
|
(a) = ROTATE_LEFT ((a), (s)); \
|
|
(a) += (b); \
|
|
}
|
|
|
|
#define HH(a, b, c, d, x, s, ac) { \
|
|
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
|
(a) = ROTATE_LEFT ((a), (s)); \
|
|
(a) += (b); \
|
|
}
|
|
|
|
#define II(a, b, c, d, x, s, ac) { \
|
|
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
|
(a) = ROTATE_LEFT ((a), (s)); \
|
|
(a) += (b); \
|
|
}
|
|
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
|
|
|
#define MD5_PAD_FIRST_BYTE 0x80 // The first byte of padding.
|
|
#define MD5_PAD_SIZE 56 // The padding function pads out to 56 bytes.
|
|
|
|
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
|
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
|
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
|
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
|
|
|
#define S11 7
|
|
#define S12 12
|
|
#define S13 17
|
|
#define S14 22
|
|
|
|
#define S21 5
|
|
#define S22 9
|
|
#define S23 14
|
|
#define S24 20
|
|
|
|
#define S31 4
|
|
#define S32 11
|
|
#define S33 16
|
|
#define S34 23
|
|
|
|
#define S41 6
|
|
#define S42 10
|
|
#define S43 15
|
|
#define S44 21
|
|
|
|
#define T1 0xd76aa478
|
|
#define T2 0xe8c7b756
|
|
#define T3 0x242070db
|
|
#define T4 0xc1bdceee
|
|
#define T5 0xf57c0faf
|
|
#define T6 0x4787c62a
|
|
#define T7 0xa8304613
|
|
#define T8 0xfd469501
|
|
#define T9 0x698098d8
|
|
#define T10 0x8b44f7af
|
|
#define T11 0xffff5bb1
|
|
#define T12 0x895cd7be
|
|
#define T13 0x6b901122
|
|
#define T14 0xfd987193
|
|
#define T15 0xa679438e
|
|
#define T16 0x49b40821
|
|
|
|
#define T17 0xf61e2562
|
|
#define T18 0xc040b340
|
|
#define T19 0x265e5a51
|
|
#define T20 0xe9b6c7aa
|
|
#define T21 0xd62f105d
|
|
#define T22 0x02441453
|
|
#define T23 0xd8a1e681
|
|
#define T24 0xe7d3fbc8
|
|
#define T25 0x21e1cde6
|
|
#define T26 0xc33707d6
|
|
#define T27 0xf4d50d87
|
|
#define T28 0x455a14ed
|
|
#define T29 0xa9e3e905
|
|
#define T30 0xfcefa3f8
|
|
#define T31 0x676f02d9
|
|
#define T32 0x8d2a4c8a
|
|
|
|
#define T33 0xfffa3942
|
|
#define T34 0x8771f681
|
|
#define T35 0x6d9d6122
|
|
#define T36 0xfde5380c
|
|
#define T37 0xa4beea44
|
|
#define T38 0x4bdecfa9
|
|
#define T39 0xf6bb4b60
|
|
#define T40 0xbebfbc70
|
|
#define T41 0x289b7ec6
|
|
#define T42 0xeaa127fa
|
|
#define T43 0xd4ef3085
|
|
#define T44 0x04881d05
|
|
#define T45 0xd9d4d039
|
|
#define T46 0xe6db99e5
|
|
#define T47 0x1fa27cf8
|
|
#define T48 0xc4ac5665
|
|
|
|
#define T49 0xf4292244
|
|
#define T50 0x432aff97
|
|
#define T51 0xab9423a7
|
|
#define T52 0xfc93a039
|
|
#define T53 0x655b59c3
|
|
#define T54 0x8f0ccc92
|
|
#define T55 0xffeff47d
|
|
#define T56 0x85845dd1
|
|
#define T57 0x6fa87e4f
|
|
#define T58 0xfe2ce6e0
|
|
#define T59 0xa3014314
|
|
#define T60 0x4e0811a1
|
|
#define T61 0xf7537e82
|
|
#define T62 0xbd3af235
|
|
#define T63 0x2ad7d2bb
|
|
#define T64 0xeb86d391
|
|
|
|
#define A_INIT 0x67452301
|
|
#define B_INIT 0xefcdab89
|
|
#define C_INIT 0x98badcfe
|
|
#define D_INIT 0x10325476
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
CMD5::CMD5()
|
|
{
|
|
}
|
|
|
|
CMD5::CMD5(CFile& InputFile)
|
|
{
|
|
// Initialize the digest.
|
|
a = A_INIT;
|
|
b = B_INIT;
|
|
c = C_INIT;
|
|
d = D_INIT;
|
|
|
|
// Now init the bit length of the input.
|
|
count[0] = 0;
|
|
count[1] = 0;
|
|
|
|
// Now perform transformation on every block of input.
|
|
do
|
|
{
|
|
// Read a block from the input.
|
|
block_idx = InputFile.Read( manip_block, MD5_BLOCK_SIZE);
|
|
|
|
if (block_idx == MD5_BLOCK_SIZE)
|
|
{
|
|
// A full block is ready to be transformed. Do so.
|
|
MD5_IncCount( MD5_BLOCK_SIZE );
|
|
MD5_Xform();
|
|
}
|
|
else
|
|
{
|
|
MD5_IncCount( block_idx );
|
|
|
|
// If the count of bytes read is not a full block,
|
|
// the end of the file has been found, and the ending should be prepared.
|
|
if (block_idx < (MD5_PAD_SIZE) )
|
|
{
|
|
// There is enough room in the block, to pad up to the correct size.
|
|
// Pad and then transform.
|
|
MD5_Pad( normal );
|
|
MD5_Xform();
|
|
}
|
|
else
|
|
{
|
|
// The block is already up to or beyond the pad size. Pad to the
|
|
// end and of the current block, and then transform it.
|
|
MD5_Pad( to_end );
|
|
MD5_Xform();
|
|
|
|
// Now create another block that is empty and pad all the way.
|
|
block_idx = 0;
|
|
MD5_Pad( finish );
|
|
MD5_Xform();
|
|
}
|
|
}
|
|
} while (block_idx == MD5_BLOCK_SIZE);
|
|
}
|
|
|
|
void CMD5::SetContent(CString csContent)
|
|
{
|
|
int iOffset = 0;
|
|
|
|
// Initialize the digest.
|
|
a = A_INIT;
|
|
b = B_INIT;
|
|
c = C_INIT;
|
|
d = D_INIT;
|
|
|
|
// Now init the bit length of the input.
|
|
count[0] = 0;
|
|
count[1] = 0;
|
|
|
|
// Now perform transformation on every block of input.
|
|
do
|
|
{
|
|
strcpy((char*)manip_block, csContent.Mid(iOffset, MD5_BLOCK_SIZE));
|
|
block_idx = strlen((const char*)manip_block);
|
|
|
|
if (block_idx == MD5_BLOCK_SIZE)
|
|
{
|
|
// A full block is ready to be transformed. Do so.
|
|
MD5_IncCount(MD5_BLOCK_SIZE);
|
|
MD5_Xform();
|
|
}
|
|
else
|
|
{
|
|
MD5_IncCount( block_idx );
|
|
|
|
// If the count of bytes read is not a full block,
|
|
// the end of the file has been found, and the ending should be prepared.
|
|
if (block_idx < (MD5_PAD_SIZE) )
|
|
{
|
|
// There is enough room in the block, to pad up to the correct size.
|
|
// Pad and then transform.
|
|
MD5_Pad( normal );
|
|
MD5_Xform();
|
|
}
|
|
else
|
|
{
|
|
// The block is already up to or beyond the pad size. Pad to the
|
|
// end and of the current block, and then transform it.
|
|
MD5_Pad( to_end );
|
|
MD5_Xform();
|
|
|
|
// Now create another block that is empty and pad all the way.
|
|
block_idx = 0;
|
|
MD5_Pad( finish );
|
|
MD5_Xform();
|
|
}
|
|
}
|
|
}
|
|
while (block_idx == MD5_BLOCK_SIZE);
|
|
}
|
|
|
|
void CMD5::MD5_Pad( MD5_PadMode PadMode )
|
|
{
|
|
switch( PadMode )
|
|
{
|
|
case normal:
|
|
// Perform normal padding.
|
|
manip_block[block_idx++] = MD5_PAD_FIRST_BYTE;
|
|
while (block_idx < MD5_PAD_SIZE)
|
|
manip_block[block_idx++] = 0;
|
|
|
|
// Now store count in this last block.
|
|
MD5_StoreCnt();
|
|
break;
|
|
|
|
case to_end:
|
|
// Pad until the end of the block.
|
|
manip_block[block_idx++] = MD5_PAD_FIRST_BYTE;
|
|
while (block_idx < MD5_BLOCK_SIZE)
|
|
manip_block[block_idx++] = 0;
|
|
break;
|
|
|
|
case finish:
|
|
// Finish padding.
|
|
while (block_idx < MD5_PAD_SIZE)
|
|
manip_block[block_idx++] = 0;
|
|
|
|
// Now store count in this last block.
|
|
MD5_StoreCnt();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CMD5::MD5_Xform()
|
|
{
|
|
// Save orig values of a,b,c,d.
|
|
UINT4 a_orig = a;
|
|
UINT4 b_orig = b;
|
|
UINT4 c_orig = c;
|
|
UINT4 d_orig = d;
|
|
|
|
// Now decode the manip_block into xform_buf;
|
|
MD5_Decode();
|
|
|
|
// Round 1.
|
|
// Let [abcd k s i] denote the operation
|
|
// a = b + ((a + F(b,c,d) + xform_buf[k] + T[i]) <<< s).
|
|
// Do the following 16 operations.
|
|
// [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4]
|
|
// [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8]
|
|
// [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12]
|
|
// [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]
|
|
|
|
FF (a, b, c, d, xform_buf[ 0], S11, T1);
|
|
FF (d, a, b, c, xform_buf[ 1], S12, T2);
|
|
FF (c, d, a, b, xform_buf[ 2], S13, T3);
|
|
FF (b, c, d, a, xform_buf[ 3], S14, T4);
|
|
FF (a, b, c, d, xform_buf[ 4], S11, T5);
|
|
FF (d, a, b, c, xform_buf[ 5], S12, T6);
|
|
FF (c, d, a, b, xform_buf[ 6], S13, T7);
|
|
FF (b, c, d, a, xform_buf[ 7], S14, T8);
|
|
FF (a, b, c, d, xform_buf[ 8], S11, T9);
|
|
FF (d, a, b, c, xform_buf[ 9], S12, T10);
|
|
FF (c, d, a, b, xform_buf[10], S13, T11);
|
|
FF (b, c, d, a, xform_buf[11], S14, T12);
|
|
FF (a, b, c, d, xform_buf[12], S11, T13);
|
|
FF (d, a, b, c, xform_buf[13], S12, T14);
|
|
FF (c, d, a, b, xform_buf[14], S13, T15);
|
|
FF (b, c, d, a, xform_buf[15], S14, T16);
|
|
|
|
// Round 2.
|
|
// Let [abcd k s i] denote the operation
|
|
// a = b + ((a + G(b,c,d) + xform_buf[k] + T[i]) <<< s).
|
|
// Do the following 16 operations.
|
|
// [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20]
|
|
// [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]
|
|
// [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28]
|
|
// [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]
|
|
|
|
GG (a, b, c, d, xform_buf[ 1], S21, T17);
|
|
GG (d, a, b, c, xform_buf[ 6], S22, T18);
|
|
GG (c, d, a, b, xform_buf[11], S23, T19);
|
|
GG (b, c, d, a, xform_buf[ 0], S24, T20);
|
|
GG (a, b, c, d, xform_buf[ 5], S21, T21);
|
|
GG (d, a, b, c, xform_buf[10], S22, T22);
|
|
GG (c, d, a, b, xform_buf[15], S23, T23);
|
|
GG (b, c, d, a, xform_buf[ 4], S24, T24);
|
|
GG (a, b, c, d, xform_buf[ 9], S21, T25);
|
|
GG (d, a, b, c, xform_buf[14], S22, T26);
|
|
GG (c, d, a, b, xform_buf[ 3], S23, T27);
|
|
GG (b, c, d, a, xform_buf[ 8], S24, T28);
|
|
GG (a, b, c, d, xform_buf[13], S21, T29);
|
|
GG (d, a, b, c, xform_buf[ 2], S22, T30);
|
|
GG (c, d, a, b, xform_buf[ 7], S23, T31);
|
|
GG (b, c, d, a, xform_buf[12], S24, T32);
|
|
|
|
// Round 3.
|
|
// Let [abcd k s t] denote the operation
|
|
// a = b + ((a + H(b,c,d) + xform_buf[k] + T[i]) <<< s).
|
|
// Do the following 16 operations.
|
|
// [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]
|
|
// [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40]
|
|
// [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]
|
|
// [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]
|
|
|
|
HH (a, b, c, d, xform_buf[ 5], S31, T33);
|
|
HH (d, a, b, c, xform_buf[ 8], S32, T34);
|
|
HH (c, d, a, b, xform_buf[11], S33, T35);
|
|
HH (b, c, d, a, xform_buf[14], S34, T36);
|
|
HH (a, b, c, d, xform_buf[ 1], S31, T37);
|
|
HH (d, a, b, c, xform_buf[ 4], S32, T38);
|
|
HH (c, d, a, b, xform_buf[ 7], S33, T39);
|
|
HH (b, c, d, a, xform_buf[10], S34, T40);
|
|
HH (a, b, c, d, xform_buf[13], S31, T41);
|
|
HH (d, a, b, c, xform_buf[ 0], S32, T42);
|
|
HH (c, d, a, b, xform_buf[ 3], S33, T43);
|
|
HH (b, c, d, a, xform_buf[ 6], S34, T44);
|
|
HH (a, b, c, d, xform_buf[ 9], S31, T45);
|
|
HH (d, a, b, c, xform_buf[12], S32, T46);
|
|
HH (c, d, a, b, xform_buf[15], S33, T47);
|
|
HH (b, c, d, a, xform_buf[ 2], S34, T48);
|
|
|
|
// Round 4.
|
|
// Let [abcd k s t] denote the operation
|
|
// a = b + ((a + I(b,c,d) + xform_buf[k] + T[i]) <<< s).
|
|
// Do the following 16 operations.
|
|
// [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]
|
|
// [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]
|
|
// [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]
|
|
// [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]
|
|
|
|
II (a, b, c, d, xform_buf[ 0], S41, T49);
|
|
II (d, a, b, c, xform_buf[ 7], S42, T50);
|
|
II (c, d, a, b, xform_buf[14], S43, T51);
|
|
II (b, c, d, a, xform_buf[ 5], S44, T52);
|
|
II (a, b, c, d, xform_buf[12], S41, T53);
|
|
II (d, a, b, c, xform_buf[ 3], S42, T54);
|
|
II (c, d, a, b, xform_buf[10], S43, T55);
|
|
II (b, c, d, a, xform_buf[ 1], S44, T56);
|
|
II (a, b, c, d, xform_buf[ 8], S41, T57);
|
|
II (d, a, b, c, xform_buf[15], S42, T58);
|
|
II (c, d, a, b, xform_buf[ 6], S43, T59);
|
|
II (b, c, d, a, xform_buf[13], S44, T60);
|
|
II (a, b, c, d, xform_buf[ 4], S41, T61);
|
|
II (d, a, b, c, xform_buf[11], S42, T62);
|
|
II (c, d, a, b, xform_buf[ 2], S43, T63);
|
|
II (b, c, d, a, xform_buf[ 9], S44, T64);
|
|
|
|
// Now perform the following additions. (That is increment each
|
|
// of the four registers by the value it had before this block
|
|
// was started.)
|
|
a += a_orig;
|
|
b += b_orig;
|
|
c += c_orig;
|
|
d += d_orig;
|
|
}
|
|
|
|
void CMD5::MD5_IncCount( int IncAmt)
|
|
{
|
|
UINT4 old_cnt0 = count[0];
|
|
|
|
count[0] += IncAmt*8;
|
|
if(count[0] < old_cnt0)
|
|
count[1]++; // Carry detection.
|
|
}
|
|
|
|
void CMD5::MD5_Decode()
|
|
{
|
|
unsigned int i, j;
|
|
|
|
for (i = 0, j = 0; j < MD5_BLOCK_SIZE; i++, j += sizeof(UINT4))
|
|
xform_buf[i] = ((UINT4)manip_block[j]) | (((UINT4)manip_block[j+1]) << 8) |
|
|
(((UINT4)manip_block[j+2]) << 16) | (((UINT4)manip_block[j+3]) << 24);
|
|
}
|
|
|
|
void CMD5::MD5_StoreCnt()
|
|
{
|
|
manip_block[MD5_PAD_SIZE+0]= unsigned int( count[0] & 0xff);
|
|
manip_block[MD5_PAD_SIZE+1]= unsigned int((count[0] >> 8) & 0xff);
|
|
manip_block[MD5_PAD_SIZE+2]= unsigned int((count[0] >> 16) & 0xff);
|
|
manip_block[MD5_PAD_SIZE+3]= unsigned int((count[0] >> 24) & 0xff);
|
|
|
|
manip_block[MD5_PAD_SIZE+4]= unsigned int(count[1] & 0xff);
|
|
manip_block[MD5_PAD_SIZE+5]= unsigned int((count[1] >> 8) & 0xff);
|
|
manip_block[MD5_PAD_SIZE+6]= unsigned int((count[1] >> 16) & 0xff);
|
|
manip_block[MD5_PAD_SIZE+7]= unsigned int((count[1] >> 24) & 0xff);
|
|
}
|
|
|
|
void CMD5::GetDigest( unsigned char* Dest)
|
|
{
|
|
Dest[0] = unsigned int(a & 0xff);
|
|
Dest[1] = unsigned int((a >> 8) & 0xff);
|
|
Dest[2] = unsigned int((a >> 16) & 0xff);
|
|
Dest[3] = unsigned int((a >> 24) & 0xff);
|
|
|
|
Dest[4] = unsigned int(b & 0xff);
|
|
Dest[5] = unsigned int((b >> 8) & 0xff);
|
|
Dest[6] = unsigned int((b >> 16) & 0xff);
|
|
Dest[7] = unsigned int((b >> 24) & 0xff);
|
|
|
|
Dest[8] = unsigned int(c & 0xff);
|
|
Dest[9] = unsigned int((c >> 8) & 0xff);
|
|
Dest[10] = unsigned int((c >> 16) & 0xff);
|
|
Dest[11] = unsigned int((c >> 24) & 0xff);
|
|
|
|
Dest[12] = unsigned int(d & 0xff);
|
|
Dest[13] = unsigned int((d >> 8) & 0xff);
|
|
Dest[14] = unsigned int((d >> 16) & 0xff);
|
|
Dest[15] = unsigned int((d >> 24) & 0xff);
|
|
}
|
|
|
|
CString CMD5::ConvertToAscii(unsigned char* lpszBuff)
|
|
{
|
|
CString csRet;
|
|
CString csHex = "0123456789abcdef";
|
|
int i, j;
|
|
unsigned long num;
|
|
unsigned long* plBuff = (unsigned long*)lpszBuff;
|
|
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
num = plBuff[i];
|
|
for(j = 0; j < 4; j++)
|
|
{
|
|
csRet += csHex[int((num >> (j * 8 + 4)) & 0x0F)];
|
|
csRet += csHex[int((num >> (j * 8)) & 0x0F)];
|
|
}
|
|
}
|
|
return csRet;
|
|
}
|
|
|