使用wincrypt进行md5加密

vc++ 专栏收录该内容
1 篇文章 0 订阅

发一下之前在用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;
}
  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值