MD5 计算 (下一代加密辅助类, Win32, C++)

CCNGHelper.h

#pragma once
#include <string>
#include <tchar.h>
#include <windows.h>
#include <bcrypt.h>#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif// 下一代加密辅助类
// 客户端: Windows Vista 及以上系统可用
// 服务器: Windows Server 2008 及以上系统可用
class CCNGHelper
{
public:CCNGHelper();~CCNGHelper();//// @brief: 初始化// @param: strAlgorithm     哈希算法名字符串, 可选类型如下://                          常见可选 "MD5", "SHA1", "SHA256", "SHA384", "SHA512"// //                          全部支持可选如下://                          "RSA", "RSA_SIGN", "DH", "DSA", "RC2", "RC4", "AES", "DES", "DESX", "3DES", "3DES_112", //                          "MD2", "MD4", "MD5", "SHA1", "SHA256", "SHA384", "SHA512",//                          "AES-GMAC", "AES-CMAC", "ECDSA_P256", "ECDSA_P384", "ECDSA_P521", "ECDH_P256", "ECDH_P384", "ECDH_P521", //                          "RNG", "FIPS186DSARNG", "DUAECRNG"//                          WINDOWS 8 及以上: "SP800_108_CTR_HMAC", "SP800_56A_CONCAT", "PBKDF2", "CAPI_KDF", "TLS1_1_KDF", "TLS1_2_KDF"//                          Windows 10 及以上: "ECDSA", "ECDH", "XTS-AES"//                          Windows 10 1803: "HKDF"//                          "CHACHA20_POLY1305"// // @ret: bool               操作是否成功bool Initialize(const _tstring& strAlgorithm = _T("MD5"));//// @brief: 反初始化// @ret: 无void Uninitialize();//// @brief: 重置// @ret: 无void Reset();//// @brief: 计算哈希值// @param: pData            数据缓冲// @param: ulSize           数据长度// @ret: bool               操作是否成功bool HashData(const void* pData, unsigned long long ulSize);//// @brief: 获取累积的哈希值结果// @param: bUpper           是否大写// @ret: _tstring           哈希值字符串_tstring FinishHash(bool bUpper = true);//// @brief: 获取文件的哈希值结果// @param: strPath          文件路径// @param: bUpper           是否大写// @ret: _tstring           哈希值结果字符串_tstring GetFileHash(const _tstring& strPath, bool bUpper = true);//// @brief: 获取数据的哈希值结果// @param: pData            数据指针// @param: ullSize          数据长度// @param: bUpper           是否大写// @ret: _tstring           哈希值结果字符串_tstring GetDataHash(const void* pData,unsigned long long ullSize,bool bUpper = true);private://// @brief: 计算哈希// @param: pData            数据指针// @param: ulSize           数据长度// @ret: 无bool _HashData(const void* pData, unsigned long ulSize);//// @brief: 字节内容转字符串// @param: pData            数据指针// @param: nSize            数据长度// @param: bUpper           是否大写// @ret: _tstring           转换后的字符串_tstring _BytesToString(const void* pData, size_t nSize, bool bUpper = true);//// @brief: 字符串转大小// @param: str              字符串// @ret: _tstring           转换后的字符串_tstring _ToUpper(const _tstring& str);//// @brief: 多字符字符串转宽字符串// @param: CodePage         代码页// @param: str              字符串// @ret: std::wstring       转换后的宽字符串std::wstring _MultiStrToWStr(UINT CodePage, const std::string& str);//// @brief: 字符串转宽字符串// @param: str              字符串// @ret: std::wstring       转换后的宽字符串std::wstring _TStrToWStr(const _tstring& str);private:BCRYPT_ALG_HANDLE       m_hAlg = NULL;              // 算法提供程序句柄BCRYPT_HASH_HANDLE      m_hHash = NULL;             // 哈希对象句柄PBYTE                   m_pbHashObject = NULL;      // 哈希对象内存PBYTE                   m_pbHash = NULL;            // 哈希值缓冲DWORD                   m_cbHash = 0;               // 哈希值缓冲大小_tstring                m_strAlgorithm;             // 算法名std::string             m_dataBuf;                  // 数据缓冲(用于文件读取)
};

CCNGHelper.cpp

#include "CCNGHelper.h"
#include <Wincrypt.h>#pragma comment(lib,"Bcrypt.lib")#define NT_SUCCESS(Status)          (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL         ((NTSTATUS)0xC0000001L)
#define FILE_HASH_BLOCK_SIZE        (1024 * 1024 * 4)CCNGHelper::CCNGHelper():m_hAlg(NULL),m_hHash(NULL),m_pbHashObject(NULL),m_pbHash(NULL),m_cbHash(0)
{}CCNGHelper::~CCNGHelper()
{Uninitialize();
}bool CCNGHelper::Initialize(const _tstring& strAlgorithm/* = _T("MD5")*/
)
{bool bSuccess = false;NTSTATUS status = STATUS_UNSUCCESSFUL;DWORD cbData = 0;DWORD cbHashObject = 0;_tstring strAlgorithmName = _ToUpper(strAlgorithm);if (m_strAlgorithm == strAlgorithmName){return true;}Uninitialize();do{// 打开一个算法句柄// https://learn.microsoft.com/zh-cn/windows/win32/api/bcrypt/nf-bcrypt-bcryptopenalgorithmproviderstatus = BCryptOpenAlgorithmProvider(&m_hAlg, //指向接收 CNG 提供程序句柄 的 BCRYPT_ALG_HANDLE 变量的指针strAlgorithmName.c_str(), //指向以 null 结尾的 Unicode 字符串的指针,该字符串标识请求的加密算法NULL, //指向以 null 结尾的 Unicode 字符串的指针,该字符串标识要加载的特定提供程序BCRYPT_HASH_REUSABLE_FLAG//修改函数行为的标志);if (!NT_SUCCESS(status)){break;}// 检索提供程序的子对象的大小(以字节为单位)// https://learn.microsoft.com/zh-cn/windows/win32/api/bcrypt/nf-bcrypt-bcryptgetpropertystatus = BCryptGetProperty(m_hAlg, //表示要获取其属性值的 CNG 对象的句柄BCRYPT_OBJECT_LENGTH, //指向以 null 结尾的 Unicode 字符串的指针,该字符串包含要检索的属性的名称(PBYTE)&cbHashObject, //接收属性值的缓冲区的地址sizeof(DWORD), //pbOutput 缓冲区的大小(以字节为单位)&cbData, //指向 ULONG 变量的指针,该变量接收复制到 pbOutput 缓冲区的字节数0 //一组标志,用于修改此函数的行为。 未为此函数定义任何标志);if (!NT_SUCCESS(status)){break;}// 在堆上分配哈希对象m_pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbHashObject);if (NULL == m_pbHashObject){break;}// 检索哈希提供程序的哈希值的大小(以字节为单位)// https://learn.microsoft.com/zh-cn/windows/win32/api/bcrypt/nf-bcrypt-bcryptgetpropertystatus = BCryptGetProperty(m_hAlg, //表示要获取其属性值的 CNG 对象的句柄BCRYPT_HASH_LENGTH, //指向以 null 结尾的 Unicode 字符串的指针,该字符串包含要检索的属性的名称(PBYTE)&m_cbHash, //接收属性值的缓冲区的地址sizeof(DWORD), //pbOutput 缓冲区的大小(以字节为单位)&cbData, //指向 ULONG 变量的指针,该变量接收复制到 pbOutput 缓冲区的字节数0 //一组标志,用于修改此函数的行为。 未为此函数定义任何标志);if (!NT_SUCCESS(status)){break;}// 在堆上分配哈希缓冲区m_pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_cbHash);if (NULL == m_pbHash){break;}// 创建哈希对象// https://learn.microsoft.com/zh-cn/windows/win32/api/bcrypt/nf-bcrypt-bcryptcreatehashstatus = ::BCryptCreateHash(m_hAlg, //创建提供程序时指定的算法必须支持哈希接口&m_hHash, //哈希或 MAC 对象的句柄m_pbHashObject, //接收哈希或 MAC 对象的缓冲区的指针cbHashObject, //pbHashObject 缓冲区的大小(以字节为单位)NULL, //指向缓冲区的指针0, //pbSecret 缓冲区的大小(以字节为单位)BCRYPT_HASH_REUSABLE_FLAG //修改函数行为的标志);if (!NT_SUCCESS(status)){break;}bSuccess = true;} while (false);if (bSuccess){m_strAlgorithm = strAlgorithmName;}else{Uninitialize();}return bSuccess;
}void CCNGHelper::Uninitialize()
{if (m_hAlg){::BCryptCloseAlgorithmProvider(m_hAlg, 0);m_hAlg = NULL;}if (m_hHash){::BCryptDestroyHash(m_hHash);m_hHash = NULL;}if (m_pbHashObject){::HeapFree(GetProcessHeap(), 0, m_pbHashObject);m_pbHashObject = NULL;}if (m_pbHash){::HeapFree(GetProcessHeap(), 0, m_pbHash);m_pbHash = NULL;}m_strAlgorithm.clear();
}void CCNGHelper::Reset()
{if (!m_strAlgorithm.empty()){// 检索从先前调用 BCryptHashData 累积的数据的哈希值(void)::BCryptFinishHash(m_hHash, //用于计算哈希或 MAC 的哈希或 MAC 对象的句柄m_pbHash, //指向接收哈希或 MAC 值的缓冲区的指针m_cbHash, //pbOutput 缓冲区的大小(以字节为单位)0 //一组标志,用于修改此函数的行为。 当前未定义任何标志,因此此参数应为零);}
}bool CCNGHelper::HashData(const void* lpData, unsigned long long ullSize
)
{const char* pDataBegin = (const char*)lpData;const unsigned long ulMaxBlockSize = UINT32_MAX;bool bSuccess = false;if (m_strAlgorithm.empty()){return false;}// 小于32位最大值则直接计算哈希值if (ullSize <= ulMaxBlockSize){return _HashData(pDataBegin, (unsigned long)ullSize);}// 分段计算哈希值while(ullSize > 0){unsigned long ulReadSize = (ullSize > ulMaxBlockSize) ? ulMaxBlockSize : (unsigned long)ullSize;if (!_HashData(pDataBegin, ulReadSize)){break;}pDataBegin += ulReadSize;ullSize -= ulReadSize;}return bSuccess;
}_tstring CCNGHelper::FinishHash(bool bUpper/* = true*/
)
{_tstring strResult;if (m_strAlgorithm.empty()){return strResult;}// 检索从先前调用 BCryptHashData 累积的数据的哈希值NTSTATUS status = ::BCryptFinishHash(m_hHash, //用于计算哈希或 MAC 的哈希或 MAC 对象的句柄m_pbHash, //指向接收哈希或 MAC 值的缓冲区的指针m_cbHash, //pbOutput 缓冲区的大小(以字节为单位)0 //一组标志,用于修改此函数的行为。 当前未定义任何标志,因此此参数应为零);if (NT_SUCCESS(status)){strResult = _BytesToString(m_pbHash, m_cbHash, bUpper);}return strResult;
}_tstring CCNGHelper::GetFileHash(const _tstring& strPath, bool bUpper/* = true*/
)
{HANDLE hFile = INVALID_HANDLE_VALUE;DWORD dwBlockSize = FILE_HASH_BLOCK_SIZE;DWORD dwBytesRead = 0;if (m_strAlgorithm.empty()){return _tstring(_T(""));}do{// 打开文件// https://learn.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-createfilewhFile = CreateFile(strPath.c_str(),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);if (INVALID_HANDLE_VALUE == hFile){break;}if (m_dataBuf.empty()){m_dataBuf.resize(dwBlockSize);}// 读取文件数据// https://learn.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-readfilewhile (::ReadFile(hFile, &m_dataBuf[0], dwBlockSize, &dwBytesRead, NULL)){if (0 == dwBytesRead){break;}if (!_HashData(&m_dataBuf[0], dwBytesRead)){break;}}} while (false);if (INVALID_HANDLE_VALUE != hFile){::CloseHandle(hFile);}return FinishHash(bUpper);
}_tstring CCNGHelper::GetDataHash(const void* pData, unsigned long long ullSize,bool bUpper/* = true*/
)
{_tstring strResult;if (m_strAlgorithm.empty()){return strResult;}if (HashData(pData, ullSize)){strResult = FinishHash(bUpper);}return strResult;
}bool CCNGHelper::_HashData(const void* lpData, unsigned long ulSize
)
{// 数据缓冲区上执行单向哈希NTSTATUS status = ::BCryptHashData(m_hHash,(PUCHAR)lpData,ulSize,0);if (!NT_SUCCESS(status)){return false;}return true;
}_tstring CCNGHelper::_BytesToString(const void* lpData, size_t nSize,bool bUpper/* = true*/
)
{const TCHAR rgbDigitsUpper[] = _T("0123456789ABCDEF");const TCHAR rgbDigitsLower[] = _T("0123456789abcdef");_tstring strResult(nSize * 2, 0);LPCBYTE lpBytes = (LPCBYTE)lpData;if (bUpper){for (DWORD i = 0; i < nSize; i++){strResult[i * 2] = rgbDigitsUpper[lpBytes[i] >> 4];strResult[i * 2 + 1] = rgbDigitsUpper[lpBytes[i] & 0x0F];}}else{for (DWORD i = 0; i < nSize; i++){strResult[i * 2] = rgbDigitsLower[lpBytes[i] >> 4];strResult[i * 2 + 1] = rgbDigitsLower[lpBytes[i] & 0x0F];}}return strResult;
}_tstring CCNGHelper::_ToUpper(const _tstring& str
)
{_tstring strResult = str;for (auto& item : strResult){if (item >= _T('a') && item <= _T('z')){item -= 0x20;}}return strResult;
}std::wstring CCNGHelper::_MultiStrToWStr(UINT CodePage, const std::string& str
)
{//计算缓冲区所需的字符长度int cchWideChar = ::MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, NULL);std::wstring strResult(cchWideChar, 0);//成功则返回写入到指示的缓冲区的字符数size_t nConverted = ::MultiByteToWideChar(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size());//调整内容长度strResult.resize(nConverted);return strResult;
}std::wstring CCNGHelper::_TStrToWStr(const _tstring& str
)
{
#ifdef _UNICODEreturn str;
#elsereturn _MultiStrToWStr(CP_ACP, str);
#endif
}

main.cpp

#include <locale.h>
#include <tchar.h>
#include "Win32Utils/CTimeUtils.h"
#include "Win32Utils/CPathUtils.h"
#include "Win32Utils/CCNGHelper.h"int _tmain(int argc, LPCTSTR argv[])
{UNREFERENCED_PARAMETER(argc);UNREFERENCED_PARAMETER(argv);::setlocale(LC_ALL, "");unsigned long long ullStartTime;unsigned long long ullEndTime;CCNGHelper cngObj;cngObj.Initialize(_T("md5"));_tstring strCngHash;_tstring strCryptHash;//system("pause");int nCount = 1000;while (true){ullStartTime = CTimeUtils::GetCurrentTickCount();for (int i = 0; i < nCount; i++){strCngHash = cngObj.GetFileHash(CPathUtils::GetCurrentModulePath(), true);}ullEndTime = CTimeUtils::GetCurrentTickCount();_tprintf(_T("CCNGHelper MD5: %s Cost time: %lld ms\n"), strCngHash.c_str(), ullEndTime - ullStartTime);system("pause");}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/783589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

7种2024年算法优化BP,实现回归,单/多变量输入,单/多步预测功能,机器学习预测全家桶再更新!...

截止到本期MATLAB机器学习预测全家桶&#xff0c;一共发了19篇关于机器学习预测代码的文章。算上这一篇&#xff0c;一共20篇&#xff01;参考文章如下&#xff1a; 1.五花八门的机器学习预测&#xff1f;一篇搞定不行吗&#xff1f; 2.机器学习预测全家桶&#xff0c;多步预测…

wails 创建Go 项目

##wails是一个可以让go和web技术编写桌面应用#安装wails go install github.com/wailsapp/wails/v2/cmd/wailslatest#检查环境 wails doctor 创建项目wails init -n AuxiliaryTools -t vue-ts拉取go.mod的依赖项 go mod tidy进入 frontend 前端安装依赖项npm install /pnpm ins…

React组件及组件通讯

组件使用 index.js import { createRoot } from react-dom/client; import App from ./App; const root createRoot(document.querySelector(#root)) root.render(<App />)App.js import Header from ./commponts/Header/index const App () > {return <div&g…

一致性广播、可靠广播、原子广播、安全因果原子广播以及与拜占庭协议结合

在分布式系统中&#xff0c;广播协议是确保信息在网络中的节点之间有效传递的关键机制。一致性广播、可靠广播、原子广播和安全因果原子广播是分布式系统中用于确保消息传递和一致性的四种不同类型的广播协议。它们各自有不同的目标和特性&#xff0c;适用于不同的应用场景。本…

自定义微信红包封面小程序,附带后端源码,快速制作个性化红包封面

此小程序适合流量主引流&#xff0c;赚广告费&#xff0c;适合广流量主&#xff0c;适合流量主。 采用云开发&#xff0c;无需服务器&#xff0c;无需域名。小程序里插入banner广告&#xff0c;插屏广告&#xff0c;视频广告&#xff0c;激励式广告。邀请好友获取抽奖机会&…

医院陪诊管理系统(源码+文档)

TOC) 文件包含内容 1、搭建视频 2、流程图 3、开题报告 4、数据库 5、参考文献 6、服务器接口文件 7、接口文档 8、任务书 9、功能图 10、环境搭建软件 11、十六周指导记录 12、答辩ppt模板 13、技术详解 14、前端后台管理&#xff08;管理端程序&#xff09; 15、项目截图 1…

2024中国(杭州)国际数字物流技术与应用展览会将于7月8日举办

2024中国&#xff08;杭州&#xff09;国际数字物流技术与应用展览会 2024年7月8-10日 | 杭州国际博览中心 同期举办&#xff1a;2024长三角快递物流供应链与技术装备展览会 数字贸易创新引领合作动能 《十四五规划》明确指出关于“加快数字化发展&#xff0c;建设数字中国…

小程序能否替代APP?专业解析在此!

在科技行业&#xff0c;每一次创新都可能引起行业的颠覆性变革。近年来&#xff0c;随着小程序技术的迅猛发展&#xff0c;业界对于它是否将替代传统APP的讨论愈演愈烈。作为一位资深科技行业分析师&#xff0c;我将从多个维度探讨小程序与APP之间的差异&#xff0c;以及它们在…

[leetcode] 哈希表

文章目录 1.有效字母的异位词 E2. 两个数组的交集 E3.快乐数 E 1.有效字母的异位词 E :::details 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t 互为字母异…

Pytorch简明教程01

文章目录 01 Pytorch基础知识1.1 Tensor简介1.2 Tensor的创建1.3 张量的操作1. 运算操作2. 矩阵运算3. 维度变换4. 扩展和压缩维度 1.4 广播机制1.5 梯度计算 01 Pytorch基础知识 主要介绍pytorch中的tensor&#xff0c;包括tensor的创建、基本操作、广播机制等 1.1 Tensor简介…

Windows安装Mysql8

新建Mysql配置文件 my.ini [mysql] # 设置mysql客户端默认字符集 default-character-setutf8 [mysqld] #设置3306端口 port 3306 # 设置mysql的安装目录 basedirD:\\KaiNeng\\mysql-8.0.26-winx64 # 设置mysql数据库的数据的存放目录 datadirD:\\KaiNeng\\m…

爬虫工作量由小到大的思维转变---<第六十四章 > Scrapy利用Bloom过滤器增强爬虫的页面去重效率

前言&#xff1a; 网络爬虫系统是信息时代获取和管理网络数据的重要工具&#xff0c;广泛应用于搜索引擎索引、数据聚合、在线研究等领域。随着网络信息的海量增长&#xff0c;爬虫系统不可避免地会面临重复内容的爬取问题。这不仅浪费了计算资源和网络带宽&#xff0c;而且还会…

24计算机考研调剂 | 中国航天科工集团第三研究所第八三五八研究所

中国航天科工集团第三研究院第八三五八研究所 2024年航天科工集团三院8358所调剂基本要求 一、8358所坐落天津&#xff0c;为定向招生&#xff08;毕业后留所工作&#xff09;&#xff1b; 二、本年度拟调剂名额4-5人&#xff1b; 三、我所接收符合条件的调剂考生&#xff1a;…

代码第三十五天-子集Ⅱ

子集Ⅱ 题目要求 解题思路 回溯法 一般情况下&#xff0c;看到题目要求[所有可能的结果]&#xff0c;而不是[结果的个数]&#xff0c;我们就知道需要暴力搜索所有的可行解了&#xff0c;可以使用[回溯法] 回溯法是一种算法思想&#xff0c;而递归式一种编程方式&#xff0c;回…

Cesium实现渐变面

一、效果图 二、实现思路 使用着色器&#xff0c;通过纹理坐标和其他参数计算出材质的颜色和透明度。通过给定的颜色、漫反射强度和透明度&#xff0c;计算出最终的反射颜色和透明度&#xff0c;并且根据给定的中心点位置和当前像素的纹理坐标&#xff0c;计算出距离中心的距离…

C++未格式化的输入/输出操作,流随机访问

未格式化的输入/输出操作 到目前为止&#xff0c;我们的程序只使用过格式化IO操作。输入和输出运算符(<<和>>)根据读取或写入的数据类型来格式化它们。输入运算符忽略空白符&#xff0c;输出运算符应用补白、精度等规则。 标准库还提供了一组低层操作&#xff0c;…

(一)kafka实战——kafka源码编译启动

前言 本节内容是关于kafka消息中间键的源码编译&#xff0c;并通过idea工具实现kafka服务器的启动&#xff0c;使用的kafka源码版本是3.6.1&#xff0c;由于kafka源码是通过gradle编译的&#xff0c;以及服务器是通过scala语言实现&#xff0c;我们要预先安装好gradle编译工具…

[已解决]ModuleNotFoundError: No module named ‘triton‘

问题描述&#xff1a;ModuleNotFoundError: No module named triton window下难以编译&#xff0c;直接下载win版本已经编译的&#xff1a; https://huggingface.co/r4ziel/xformers_pre_built/blob/main/triton-2.0.0-cp310-cp310-win_amd64.wh

每日一练 找无重复字符的最长子串

我们来看下这个题目&#xff0c;我们要统计的是不重复的子串&#xff0c;我们可以使用“滑动窗口法”&#xff0c;其实我们很容易就能想到思路。 我们的左窗代表我们目前遍历的开始&#xff0c;即我们遍历的子串的开头&#xff0c;右窗从左窗开始进行遍历&#xff0c;每次遍历…

【C语言终章】预处理详解(上)

【C语言终章】预处理详解&#xff08;上&#xff09; 当你看到了这里时&#xff0c;首先要恭喜你&#xff01;因为这里就是C语言的最后一站了&#xff0c;你的编程大能旅途也将从此站开始&#xff0c;为坚持不懈的你鼓个掌吧&#xff01; &#x1f955;个人主页&#xff1a;开敲…