发一下之前在用c++写windows下的爬虫的时候用到的代码,非常羡慕php用自带的md5函数直接使用即可。在windows环境下可以用第三方库或winapi来进行md5摘要。
以下为自己写好的一个md5加密类,为了方便类成员变量都采用了public的权限,仅供参考
## GlobalLib 自己定义的一些宏工具和可能用到的头文件(因为是之前项目里的所以我直接拷贝了) ##
#pragma once
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <locale.h>
#include <map>
#include <wincrypt.h>
#include <Winhttp.h>
#include <sstream>
#pragma comment(lib, "winhttp.lib")
#pragma comment(lib,"ws2_32")
using namespace std;
#define wstrlen wcslen
#define WCPY(D,S,L) memcpy_s(D,sizeof(WCHAR)* L,S,sizeof(WCHAR)* L);
#define GET_ERROR_STR(dwError) \
{WCHAR *szError = NULL;\
setlocale(LC_CTYPE, ".936");\
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, \
NULL, \
dwError, \
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \
(LPTSTR)&szError, 0, NULL); \
wprintf(L"Happen Error:%s \nErrorNumber:%d\n",szError,dwError);}
//调试开关
#define _M_DEBUG_ 1
#ifdef _M_DEBUG_
#define OO wcout
#endif // _M_DEBUG_
#ifndef _M_DEBUG_
#define GET_ERROR_STR(dwError) ;
#define OO /##/
#endif // !_M_DEBUG_
## 声明文件 ##
#pragma once
#include "GlobalLib.h"
//wincrypt加密
class _Crypt
{
public:
_Crypt();
~_Crypt();
//初始化相关数据结构
bool init();
//传入要加密的数据和长度
bool SetMd5(BYTE *data, DWORD len);
//处理要加密的数据 并得到返回的加密结果 到类缓冲区
bool GetMd5();
//输出md5字符串
bool DisplayMd5();
private:
//如果要在_Crypt对象中 多次使用md5加密需要 销毁之前的m_hHash hash对象的句柄 重新打开 进行必要的清理工作 内置方法
void clear();
public:
bool m_InitRes[3];
HCRYPTPROV m_hCrypt;
HCRYPTHASH m_hHash;
BYTE* m_md5Buf;
DWORD m_md5BufLen;
char* m_md5CharBuf;
};
## 实现文件 ##
#include "stdafx.h"
#include "_Crypt.h"
_Crypt::_Crypt() :m_hCrypt(0), m_hHash(0), m_md5Buf(NULL), m_md5BufLen(0), m_md5CharBuf(NULL)
{
this->m_InitRes[0] = this->m_InitRes[1] = this->m_InitRes[2] = 0;
}
_Crypt::~_Crypt()
{
if (this->m_InitRes[0])
CryptReleaseContext(this->m_hCrypt, 0);
this->clear();
}
bool _Crypt::init()
{
//创建初始化加密必要的对象 CryptAcquireContext无论什么加密都要先有他返回的句柄
this->m_InitRes[0] = CryptAcquireContext(&this->m_hCrypt, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
if (!this->m_InitRes[0])
{
OO << L"CryptAcquireContext failed!" << endl;
GET_ERROR_STR(GetLastError())
return false;
}
return true;
}
void _Crypt::clear()
{
if (this->m_InitRes[1])
{
CryptDestroyHash(this->m_hHash);
this->m_hHash = NULL;
}
if (NULL != this->m_md5Buf)
{
delete this->m_md5Buf;
this->m_md5Buf = NULL;
}
if (NULL != this->m_md5CharBuf)
{
delete this->m_md5CharBuf;
this->m_md5CharBuf = NULL;
}
this->m_md5BufLen = 0;
this->m_InitRes[1] = this->m_InitRes[2] =false;
}
bool _Crypt::SetMd5(BYTE *data, DWORD len)
{
this->clear();
//创建 hash加密对象 CryptCreateHash 返回hash对象句柄
this->m_InitRes[1] = CryptCreateHash(this->m_hCrypt, CALG_MD5, 0, 0, &this->m_hHash);
if (!this->m_InitRes[1])
{
OO << L"CryptCreateHash failed!" << endl;
GET_ERROR_STR(GetLastError())
return false;
}
//如果初始化失败 则不能进行md5加密
if (!this->m_InitRes[0] || !this->m_InitRes[1])
return false;
//传入要加密的数据 给hash对象
this->m_InitRes[2] = CryptHashData(this->m_hHash, data, len, 0);
if (!this->m_InitRes[2])
{
OO << L"CryptHashData failed!" << endl;
GET_ERROR_STR(GetLastError())
return false;
}
return true;
}
bool _Crypt::GetMd5()
{
if (!this->m_InitRes[0] || !this->m_InitRes[2] || !this->m_InitRes[1])
return false;
//取得加密后的md5值 结果保存在 本对象的buf中 析构函数负责回收
//m_md5Buf中的值 和 md5字符串的关系 : dwRealLen 获得的是md5缓存的字节长度 但是不是md5字符长度
//要得到md5字符 需要转换 如dwRealLen=16 那么16字节 缓存内 转成16进制 一个十六进制位代表一个md5字符 所以16字节有32个十六进制位 是32个md5字符串
DWORD dwRealLen = 0;
DWORD dwPramaSize = sizeof(dwRealLen);
//获得md5 缓存长度
if (!CryptGetHashParam(this->m_hHash, HP_HASHSIZE, (BYTE*)&dwRealLen, &dwPramaSize, 0))
{
OO << L"CryptGetHashParam get len failed!" << endl;
GET_ERROR_STR(GetLastError())
return false;
}
this->m_md5Buf = new BYTE[dwRealLen];
if (this->m_md5Buf == NULL)
return false;
if (!CryptGetHashParam(this->m_hHash, HP_HASHVAL, this->m_md5Buf, &dwRealLen, 0))
{
OO << L"CryptGetHashParam get buf failed!" << endl;
delete this->m_md5Buf;
this->m_md5Buf = NULL;
GET_ERROR_STR(GetLastError())
return false;
}
this->m_md5BufLen = dwRealLen;
this->m_md5CharBuf = new char[dwRealLen * 2 + 1];
if (NULL == this->m_md5CharBuf)
{
OO << L"CryptGetHashParam get buf failed!" << endl;
delete this->m_md5Buf;
this->m_md5Buf = NULL;
GET_ERROR_STR(GetLastError())
return false;
}
for (unsigned int count = 0; count < this->m_md5BufLen; count++)
{
//按%x输出到md5字符缓存 _snprintf_s 一次 就输出了3个字符 一个%x是2个十六进制位 再+ \0 == 3
// *2+1= 16*2+1=33 0-32 count[0-15]0-30 m_md5CharBuf[30] 30 31 32
_snprintf_s(&this->m_md5CharBuf[count * 2], 3, 3, "%02x", (unsigned short)this->m_md5Buf[count]);
}
m_md5CharBuf[dwRealLen * 2] = '\0';
return true;
}
bool _Crypt::DisplayMd5()
{
if (this->m_md5CharBuf == NULL || this->m_md5Buf == NULL || this->m_md5BufLen <= 0 || !this->m_InitRes[0] || !this->m_InitRes[2] || !this->m_InitRes[1])
return false;
cout << m_md5CharBuf << endl;
return true;
}