좌측의 md5처럼 결과값이 나옵니다.
#include <memory.h>
#include <windows.h>
#include <windowsx.h>
#include <shellapi.h>
#include <htmlhelp.h>
#include "resource.h"
#include "MD5.h"
#define VERSION_MAJOR 1
#define VERSION_MINOR 0
#define DEF_WIN_WIDTH 480
#define DEF_WIN_HEIGHT 120
#define DEF_STRBUF_SIZE 8192
#define TEXT_BORDER_SIZE 4
#define TEXT_LINE_GAP 4
#define CLASS_NAME TEXT("MAINWIN")
// forwards
LRESULT CALLBACK MainWin_WinProc(HWND, UINT, WPARAM, LPARAM);
BOOL MainWin_OnCreate(HWND, LPCREATESTRUCT);
void MainWin_OnDestroy(HWND);
void MainWin_OnPaint(HWND);
void MainWin_OnDropFiles(HWND, HDROP);
LRESULT MainWin_OnMenuExec(HWND);
LRESULT MainWin_OnMenuExit(HWND);
LRESULT MainWin_OnMenuAbout(HWND);
LRESULT MainWin_OnMenuCopy(HWND);
LRESULT MainWin_OnMenuHelp(HWND);
DWORD CalcFileMD5(TCHAR*, BYTE*);
void MainWin_ShowMessage(TCHAR* szMess);
//////////////////////////////////////////////////////////////////////////////
// creation and destruction
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// the file checksum routine
#define IOBUF_SIZE 32768
// constants for MD5Transform routine.
#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
// prototypes of the support routines
void _MD5_transform (unsigned int[4], unsigned char[64]);
void _MD5_encode (unsigned char *, unsigned int*, unsigned int);
void _MD5_decode (unsigned int*, unsigned char *, unsigned int);
// F, G, H and I are basic MD5 functions.
#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)))
// ROTATE_LEFT rotates x left n bits.
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (unsigned int)(ac);\
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (unsigned int)(ac);\
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (unsigned int)(ac);\
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (unsigned int)(ac);\
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
void MD5_API MD5_Initialize(PMD5CTX pCtx)
{
MD5_Reset(pCtx);
}
void MD5_API MD5_Reset
(PMD5CTX pCtx)
{
pCtx->count[0] = pCtx->count[1] = 0;
// load magic init. constants.
pCtx->state[0] = 0x67452301;
pCtx->state[1] = 0xefcdab89;
pCtx->state[2] = 0x98badcfe;
pCtx->state[3] = 0x10325476;
}
void MD5_API MD5_Update
(PMD5CTX pCtx,
const void* pData,
unsigned int lNumOfBytes)
{
unsigned char* pInput = (unsigned char*) pData;
unsigned int lI, lIndex, lPartLen;
// compute number of bytes mod 64
lIndex = (unsigned int)((pCtx->count[0] >> 3) & 0x3F);
// update number of bits
if ((pCtx->count[0] += ((unsigned int)lNumOfBytes << 3)) < ((unsigned int)lNumOfBytes << 3))
pCtx->count[1]++;
pCtx->count[1] += ((unsigned int)lNumOfBytes >> 29);
lPartLen = 64 - lIndex;
// transform as many times as possible.
if (lNumOfBytes >= lPartLen)
{
memcpy(&pCtx->buffer[lIndex], pInput, lPartLen);
_MD5_transform (pCtx->state, pCtx->buffer);
for (lI = lPartLen; lI + 63 < lNumOfBytes; lI += 64)
_MD5_transform (pCtx->state, &pInput[lI]);
lIndex = 0;
}
else lI = 0;
// buffer remaining input
memcpy(&pCtx->buffer[lIndex],
&pInput[lI],
lNumOfBytes - lI);
}
void MD5_API MD5_Final
(unsigned char digest[MD5_DIGESTSIZE],
PMD5CTX pCtx )
{
// to allow multithreading we have to locate the padding memory here
unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
unsigned char bits[8];
unsigned int lIndex, lPadLen;
// save number of bits
_MD5_encode(bits, pCtx->count, 8);
// pad out to 56 mod 64
lIndex = (unsigned int)((pCtx->count[0] >> 3) & 0x3f);
lPadLen = (lIndex < 56) ? (56 - lIndex) : (120 - lIndex);
MD5_Update(pCtx, PADDING, lPadLen);
// append length (before padding)
MD5_Update(pCtx, bits, 8);
// store state in digest
_MD5_encode(digest, pCtx->state, 16);
// clear sensitive information.
memset(pCtx, 0, sizeof(MD5CTX));
}
// (the selftest strings and digests)
static char* selfTestSource[3] =
{
"hellooo nurse!",
"whoa nelly, says Sherman, the Shark",
"01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
};
static unsigned char selfTestDigest[3][MD5_DIGESTSIZE] =
{
{ 0x13, 0x12, 0x04, 0x84, 0x56, 0x62, 0x22, 0xdf,
0xcf, 0xac, 0x4f, 0xd4, 0x1e, 0x78, 0x18, 0x90 },
{ 0x1f, 0x6a, 0x8e, 0x65, 0xba, 0x18, 0xb7, 0x74,
0xc0, 0xc1, 0xed, 0xcb, 0xe6, 0x29, 0xb4, 0x95 },
{ 0x9c, 0xdc, 0xa7, 0xfa, 0x46, 0xc7, 0xc7, 0x1a,
0x5c, 0xfe, 0xd3, 0xbc, 0x99, 0x9e, 0x2f, 0x91 }
};
int MD5_API MD5_SelfTest()
{
int nI, nJ;
MD5CTX ctx;
unsigned char actDigest[MD5_DIGESTSIZE];
// run all tests
for (nI = 0; nI < 3; nI++)
{
MD5_Initialize(&ctx);
MD5_Update(&ctx,
selfTestSource[nI],
sizeof(selfTestSource[nI]));
MD5_Final(actDigest, &ctx);
for (nJ = 0; nJ < sizeof(actDigest); nJ++)
{
if (actDigest[nJ] != selfTestDigest[nI][nJ]) return 0;
}
}
return 1;
}
// basic transformation, transforms state based on block.
void _MD5_transform
(unsigned int state[4],
unsigned char block[64])
{
unsigned int lA = state[0], lB = state[1], lC = state[2], lD = state[3];
unsigned int x[16];
_MD5_decode (x, block, 64);
// round 1
FF ( lA, lB, lC, lD, x[ 0], S11, 0xd76aa478); // 1
FF ( lD, lA, lB, lC, x[ 1], S12, 0xe8c7b756); // 2
FF ( lC, lD, lA, lB, x[ 2], S13, 0x242070db); // 3
FF ( lB, lC, lD, lA, x[ 3], S14, 0xc1bdceee); // 4
FF ( lA, lB, lC, lD, x[ 4], S11, 0xf57c0faf); // 5
FF ( lD, lA, lB, lC, x[ 5], S12, 0x4787c62a); // 6
FF ( lC, lD, lA, lB, x[ 6], S13, 0xa8304613); // 7
FF ( lB, lC, lD, lA, x[ 7], S14, 0xfd469501); // 8
FF ( lA, lB, lC, lD, x[ 8], S11, 0x698098d8); // 9
FF ( lD, lA, lB, lC, x[ 9], S12, 0x8b44f7af); // 10
FF ( lC, lD, lA, lB, x[10], S13, 0xffff5bb1); // 11
FF ( lB, lC, lD, lA, x[11], S14, 0x895cd7be); // 12
FF ( lA, lB, lC, lD, x[12], S11, 0x6b901122); // 13
FF ( lD, lA, lB, lC, x[13], S12, 0xfd987193); // 14
FF ( lC, lD, lA, lB, x[14], S13, 0xa679438e); // 15
FF ( lB, lC, lD, lA, x[15], S14, 0x49b40821); // 16
// round 2
GG ( lA, lB, lC, lD, x[ 1], S21, 0xf61e2562); // 17
GG ( lD, lA, lB, lC, x[ 6], S22, 0xc040b340); // 18
GG ( lC, lD, lA, lB, x[11], S23, 0x265e5a51); // 19
GG ( lB, lC, lD, lA, x[ 0], S24, 0xe9b6c7aa); // 20
GG ( lA, lB, lC, lD, x[ 5], S21, 0xd62f105d); // 21
GG ( lD, lA, lB, lC, x[10], S22, 0x2441453); // 22
GG ( lC, lD, lA, lB, x[15], S23, 0xd8a1e681); // 23
GG ( lB, lC, lD, lA, x[ 4], S24, 0xe7d3fbc8); // 24
GG ( lA, lB, lC, lD, x[ 9], S21, 0x21e1cde6); // 25
GG ( lD, lA, lB, lC, x[14], S22, 0xc33707d6); // 26
GG ( lC, lD, lA, lB, x[ 3], S23, 0xf4d50d87); // 27
GG ( lB, lC, lD, lA, x[ 8], S24, 0x455a14ed); // 28
GG ( lA, lB, lC, lD, x[13], S21, 0xa9e3e905); // 29
GG ( lD, lA, lB, lC, x[ 2], S22, 0xfcefa3f8); // 30
GG ( lC, lD, lA, lB, x[ 7], S23, 0x676f02d9); // 31
GG ( lB, lC, lD, lA, x[12], S24, 0x8d2a4c8a); // 32
// round 3
HH ( lA, lB, lC, lD, x[ 5], S31, 0xfffa3942); // 33
HH ( lD, lA, lB, lC, x[ 8], S32, 0x8771f681); // 34
HH ( lC, lD, lA, lB, x[11], S33, 0x6d9d6122); // 35
HH ( lB, lC, lD, lA, x[14], S34, 0xfde5380c); // 36
HH ( lA, lB, lC, lD, x[ 1], S31, 0xa4beea44); // 37
HH ( lD, lA, lB, lC, x[ 4], S32, 0x4bdecfa9); // 38
HH ( lC, lD, lA, lB, x[ 7], S33, 0xf6bb4b60); // 39
HH ( lB, lC, lD, lA, x[10], S34, 0xbebfbc70); // 40
HH ( lA, lB, lC, lD, x[13], S31, 0x289b7ec6); // 41
HH ( lD, lA, lB, lC, x[ 0], S32, 0xeaa127fa); // 42
HH ( lC, lD, lA, lB, x[ 3], S33, 0xd4ef3085); // 43
HH ( lB, lC, lD, lA, x[ 6], S34, 0x4881d05); // 44
HH ( lA, lB, lC, lD, x[ 9], S31, 0xd9d4d039); // 45
HH ( lD, lA, lB, lC, x[12], S32, 0xe6db99e5); // 46
HH ( lC, lD, lA, lB, x[15], S33, 0x1fa27cf8); // 47
HH ( lB, lC, lD, lA, x[ 2], S34, 0xc4ac5665); // 48
// round 4
II ( lA, lB, lC, lD, x[ 0], S41, 0xf4292244); // 49
II ( lD, lA, lB, lC, x[ 7], S42, 0x432aff97); // 50
II ( lC, lD, lA, lB, x[14], S43, 0xab9423a7); // 51
II ( lB, lC, lD, lA, x[ 5], S44, 0xfc93a039); // 52
II ( lA, lB, lC, lD, x[12], S41, 0x655b59c3); // 53
II ( lD, lA, lB, lC, x[ 3], S42, 0x8f0ccc92); // 54
II ( lC, lD, lA, lB, x[10], S43, 0xffeff47d); // 55
II ( lB, lC, lD, lA, x[ 1], S44, 0x85845dd1); // 56
II ( lA, lB, lC, lD, x[ 8], S41, 0x6fa87e4f); // 57
II ( lD, lA, lB, lC, x[15], S42, 0xfe2ce6e0); // 58
II ( lC, lD, lA, lB, x[ 6], S43, 0xa3014314); // 59
II ( lB, lC, lD, lA, x[13], S44, 0x4e0811a1); // 60
II ( lA, lB, lC, lD, x[ 4], S41, 0xf7537e82); // 61
II ( lD, lA, lB, lC, x[11], S42, 0xbd3af235); // 62
II ( lC, lD, lA, lB, x[ 2], S43, 0x2ad7d2bb); // 63
II ( lB, lC, lD, lA, x[ 9], S44, 0xeb86d391); // 64
state[0] += lA;
state[1] += lB;
state[2] += lC;
state[3] += lD;
// lClear sensitive information
memset(x, 0, 16);
}
// encodes input (unsigned int) into output (unsigned char),
// assumes that lLen is a multiple of 4
void _MD5_encode
(unsigned char* pOutput,
unsigned int* pInput,
unsigned int lLen)
{
unsigned int lI, lJ;
for (lI = 0, lJ = 0; lJ < lLen; lI++, lJ += 4)
{
pOutput[lJ] = (unsigned char)(pInput[lI] & 0x0ff);
pOutput[lJ + 1] = (unsigned char)((pInput[lI] >> 8) & 0x0ff);
pOutput[lJ + 2] = (unsigned char)((pInput[lI] >> 16) & 0x0ff);
pOutput[lJ + 3] = (unsigned char)((pInput[lI] >> 24) & 0x0ff);
}
}
// encodes input (unsigned char) into output (unsigned int),
// assumes that lLen is a multiple of 4.
void _MD5_decode
(unsigned int* pOutput,
unsigned char* pInput,
unsigned int lLen)
{
unsigned int lI, lJ;
for (lI = 0, lJ = 0; lJ < lLen; lI++, lJ += 4)
pOutput[lI] = ((unsigned int)pInput[lJ]) |
(((unsigned int)pInput[lJ + 1]) << 8) |
(((unsigned int)pInput[lJ + 2]) << 16) |
(((unsigned int)pInput[lJ + 3]) << 24);
}
DWORD md5(TCHAR* szFileName,char* result)
{
HANDLE hFile;
DWORD dwRead;
DWORD dwErr;
BYTE ioBuf[IOBUF_SIZE];
MD5CTX hasher;
BOOL blReadOK;
BYTE* p;
hFile = CreateFile(szFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
0);
if (INVALID_HANDLE_VALUE == hFile)
{
return GetLastError();
}
MD5_Initialize(&hasher);
while (TRUE == (blReadOK = ReadFile(hFile,
ioBuf,
IOBUF_SIZE,
&dwRead,
NULL)))
{
if (0 == dwRead) break;
MD5_Update(&hasher, ioBuf, dwRead);
}
if (!blReadOK)
{
dwErr = GetLastError();
if (dwErr != NOERROR)
{
dwErr = (ERROR_INVALID_HANDLE == dwErr) ? NOERROR : dwErr;
}
}
else
{
dwErr = NOERROR;
MD5_Final(p, &hasher);
}
wsprintf(result,"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
p[0],p[1],p[2],p[3],p[4]
,p[5],p[6],p[7],p[8],p[9]
,p[10],p[11],p[12],p[13],p[14],p[15]);
CloseHandle(hFile);
return dwErr;
}
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////// md5.h /////////////////////////////////////
#include <windows.h>
DWORD md5(TCHAR*,char*);
#ifndef __MD5_H
#define __MD5_H
#define MD5_API
#ifdef __cplusplus
extern "C" {
#endif
// size of an MD5 digest
#define MD5_DIGESTSIZE 16
// MD5 context
typedef struct
{
unsigned int state[4]; // state (ABCD)
unsigned int count[2]; // number of bits, modulo 2^64 (lsb first)
unsigned char buffer[64]; // input buffer
}
MD5CTX, *PMD5CTX;
/*
* initialization
* -> pointer to MD5 context
*/
void MD5_API
MD5_Initialize (PMD5CTX);
/*
* resets an MD5 context
* -> context to rest
*/
void MD5_API
MD5_Reset (PMD5CTX);
/*
* block update operation, continues an MD5 message-digest operation,
* processing another message block, and updating the context
* -> pointer to MD5 context
* -> pointer to input buffer, which is treated as a byte buffer
* -> number of bytes to scramble
*/
void MD5_API
MD5_Update (PMD5CTX, const void*, unsigned int);
/*
* MD5 finalization, ends an MD5 message-digest operation,
* writing the message digest and clearing the context
* -> buffer where to copy the digest's bytes
* -> pointer to MD5 context
*/
void MD5_API
MD5_Final (unsigned char[MD5_DIGESTSIZE], PMD5CTX);
/*
* selftest
* <- 1: selftest succeeded / 0: error
*/
int MD5_API
MD5_SelfTest();
#ifdef __cplusplus
}
#endif
#endif