Windows的SDK提供了MD5的算法,但没有提供.h方式的调用方式,需要动态加载DLL。
本文是C++方式的封装,主要涉及2个类:MD5和MD5Impl。前者是用户接口,后者是具体实现。提供2个class的原因在于屏蔽MD5用到的数据结构,简化调用方式。
MD5.h
#ifndef __MD5_H
#define __MD5_H
class MD5Impl;
class MD5
{
public:
MD5();
~MD5();
void Init();
void Update(unsigned char* buffer, unsigned int inlen);
void Final();
void GetDigest(unsigned char digest[]);
private:
MD5Impl* m_pImpl;
};
#endif
MD5.cpp
#include "MD5.h"
#include "MD5Impl.h"
MD5::MD5():m_pImpl(new MD5Impl())
{
}
MD5::~MD5()
{
delete m_pImpl;
}
void MD5::Init()
{
m_pImpl->Init();
}
void MD5::Update(unsigned char* buffer, unsigned int inlen)
{
m_pImpl->Update(buffer, inlen);
}
void MD5::Final()
{
m_pImpl->Final();
}
void MD5::GetDigest(unsigned char digest[])
{
m_pImpl->GetDigest(digest);
}
MD5Impl.h
#ifndef __MD5IMPL_H
#define __MD5IMPL_H
#include <windows.h>
typedef struct {
ULONG i[2];
ULONG buf[4];
unsigned char in[64];
unsigned char digest[16];
} MD5_CONTEXT;
typedef void (WINAPI* TypeMD5Init) (MD5_CONTEXT *);
typedef void (WINAPI* TypeMD5Update) (MD5_CONTEXT *, const unsigned char *, unsigned int);
typedef void (WINAPI* TypeMD5Final) (MD5_CONTEXT *);
class MD5Impl
{
public:
MD5Impl();
~MD5Impl();
bool Init();
void Update(unsigned char* buffer, unsigned int inlen);
void Final();
void GetDigest(unsigned char digest[]);
private:
bool Load();
private:
MD5_CONTEXT m_context;
HMODULE m_hDLL;
TypeMD5Init m_fMD5Init;
TypeMD5Update m_fMD5Update;
TypeMD5Final m_fMD5Final;
};
#endif
MD5Impl.cpp
#include "MD5Impl.h"
#include <cassert>
MD5Impl::MD5Impl()
:m_context(), m_hDLL(NULL), m_fMD5Init(NULL), m_fMD5Update(NULL), m_fMD5Final(NULL)
{
}
MD5Impl::~MD5Impl()
{
if (m_hDLL) {
FreeLibrary(m_hDLL);
m_hDLL = NULL;
m_fMD5Init = NULL;
m_fMD5Update = NULL;
m_fMD5Final = NULL;
}
}
bool MD5Impl::Init()
{
if (NULL ==m_hDLL) {
if (!Load()) return false;
}
m_fMD5Init(&m_context);
return true;
}
void MD5Impl::Update(unsigned char* buffer, unsigned int inlen)
{
if (NULL == m_hDLL) return;
m_fMD5Update(&m_context, buffer, inlen);
}
void MD5Impl::Final()
{
if (NULL == m_hDLL) return;
m_fMD5Final(&m_context);
}
void MD5Impl::GetDigest(unsigned char digest[])
{
if (NULL == m_hDLL) return;
memcpy(digest, m_context.digest, 16);
}
bool MD5Impl::Load()
{
assert(NULL == m_hDLL);
m_hDLL = LoadLibrary("advapi32.dll");
if (NULL == m_hDLL) return false;
m_fMD5Init = (TypeMD5Init)GetProcAddress(m_hDLL, "MD5Init");
m_fMD5Update = (TypeMD5Update)GetProcAddress(m_hDLL, "MD5Update");
m_fMD5Final = (TypeMD5Final)GetProcAddress(m_hDLL, "MD5Final");
return true;
}
#include "StringUtility.h"
#include <cstdio>
void StringUtility::DumpHex(const unsigned char* buffer, unsigned int len)
{
if (NULL == buffer) return;
for (unsigned int i = 0; i < len; i++) {
printf("%02X ", buffer[i]);
}
printf("\n");
}
#include <cstdio>
#include <cstring>
#include "MD5.h"
#include "StringUtility.h"
int main()
{
const char* s = "Hello, world!";
MD5 md5;
md5.Init();
md5.Update((unsigned char*)s, strlen(s));
md5.Final();
unsigned char digest[16] = {0};
md5.GetDigest(digest);
StringUtility::DumpHex(digest, 16);
return 0;
}
运行结果:
6C D3 55 6D EB 0D A5 4B CA 06 0B 4C 39 47 98 39
请按任意键继续. . .