C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++ CryptoPP计算Hash值

C++通过CryptoPP计算Hash值的过程详解

作者:微软技术分享

Crypto++ (CryptoPP) 是一个用于密码学和加密的C++库,它是一个开源项目,提供了大量的密码学算法和功能,本文小编给大家介绍了C++通过CryptoPP计算Hash值的过程,文中通过代码示例给大家介绍的非常详细,需要的朋友可以参考下

Crypto++ (CryptoPP) 是一个用于密码学和加密的 C++ 库。它是一个开源项目,提供了大量的密码学算法和功能,包括对称加密、非对称加密、哈希函数、消息认证码 (MAC)、数字签名等。Crypto++ 的目标是提供高性能和可靠的密码学工具,以满足软件开发中对安全性的需求。

该库包含了许多常见的密码学算法,如AES、DES、RSA、DSA、SHA等,使开发者能够轻松地在他们的应用程序中实现安全性和加密功能。Crypto++ 是以面向对象的方式设计的,因此它的使用通常涉及使用类和对象来表示不同的密码学概念和算法。

Crypto++ 提供了许多特性,包括多平台支持(Windows、Linux、macOS等)、容易使用的 API、高性能的实现、丰富的文档和社区支持。在使用 Crypto++ 之前,你需要确保正确地配置和链接 Crypto++ 库到你的项目中。

编译Crypto库

目前Crypto库的最新版本为8.90,读者可自行下载对应的库源代码,下载好以后使用Visual Studio工具打开源文件中的cryptest.sln文件。

打开以后选中调试菜单中的属性页面,此时将运行库修改为多线程/MT模式,否则虽可以编译通过但这个库却无法被正常使用,此处是一个坑。

此时选中解决方案,并直接点击重新编译库,这个过程可能需要等待一段时间,更具设备的配置而不同读者可在最底部看到输出进度;

当编译成功以后,读者可以来到cryptopp890\Win32\Output\Release目录下,该目录下的则是编译成功后的lib库文件,可以将这3个文件全部保存在新建的lib文件夹内。

接着在cryptopp890文件夹下直接搜索所有的*.h头文件,并放入到新建的include文件夹内,此时我们就有了最新版本的开发工具包了。

使用该库也很容易,只需要包含Include与Lib库文件即可,如下图所示配置;

使用MD5算法

MD5(Message Digest Algorithm 5)是一种常见的哈希函数,用于产生128位的散列值(通常以32位的十六进制数表示)。MD5广泛用于检查数据完整性、数字签名、密码存储等领域。

以下是 MD5 算法的基本概述:

MD5 算法的设计目标是产生一个唯一的(或极其难以相同)散列值,以便在密码存储、数字签名和数据完整性检查等场景中使用。然而,由于MD5存在一些安全性问题,特别是其易受碰撞攻击的漏洞,现在不再被推荐用于安全性要求较高的场景。对于安全性要求较高的应用,推荐使用更强大和安全的哈希函数,如SHA-256或SHA-3。

如下这段代码中涉及到一些特殊的类,这里将分别介绍功能;

#include <Windows.h>
#include <iostream>

#include <md5.h>
#include <files.h>
#include <hex.h>

using namespace std;
using namespace CryptoPP;

#pragma comment(lib,"cryptlib.lib")

int main(int argc, char* argv[])
{
	// 定义MD5类
	MD5 md5;

	// 计算字符串MD5
	string src = "Hello World";
	string dst;

	StringSource(src, true, new HashFilter(md5, new HexEncoder(new StringSink(dst))));
	std::cout << "字符串hash = " << dst << std::endl;

	// 计算字节数组MD5
	string digest;
	BYTE pData[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	DWORD dwDataSize = sizeof(pData);

	StringSource(pData, dwDataSize, true, new HashFilter(md5, new HexEncoder(new StringSink(digest))));
	std::cout << "数组长度 = " << dwDataSize << std::endl;
	std::cout << "数组hash = " << digest << std::endl;

	system("pause");
	return 0;
}

运行后则可分别输出字符串与数组的MD5值,如下图所示;

如果需要从文件中读取则需要使用FileSource类,在计算MD5之前先将文件读入内存在进行计算,如下所示;

#include <Windows.h>
#include <iostream>

#include <md5.h>
#include <files.h>
#include <hex.h>

using namespace std;
using namespace CryptoPP;

#pragma comment(lib,"cryptlib.lib")

// 计算文件MD5
string CalMD5ByFile(char *pszFileName)
{
	string value;
	MD5 md5;
	FileSource(pszFileName, true, new HashFilter(md5, new HexEncoder(new StringSink(value))));
	return value;
}

// 计算数据MD5
string CalMD5ByMemory(PBYTE pData, DWORD dwDataSize)
{
	string value;
	MD5 md5;
	StringSource(pData, dwDataSize, true, new HashFilter(md5, new HexEncoder(new StringSink(value))));
	return value;
}

int main(int argc, char* argv[])
{
	// 定义MD5类
	MD5 md5;

	// 计算文件的MD5
	string md51 = CalMD5ByFile("d://lyshark.exe");
	printf("md5 = %s\n", md51.c_str());

	// 计算文件内存的MD5
	HANDLE hFile2 = CreateFile("d://lyshark.exe", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);

	// 取文件长度
	DWORD dwFileSize2 = GetFileSize(hFile2, NULL);
	BYTE *pData2 = new BYTE[dwFileSize2];

	// 读文件到内存
	ReadFile(hFile2, pData2, dwFileSize2, NULL, NULL);

	// 计算MD5
	string md52 = CalMD5ByMemory(pData2, dwFileSize2);
	printf("md5 = %s\n", md52.c_str());

	system("pause");
	return 0;
}

如下图所示,是计算后得到的文件的MD5值;

使用CRC32算法

CRC32(Cyclic Redundancy Check,循环冗余校验)是一种广泛用于数据校验的错误检测算法。它基于多项式除法,在计算机领域中常用于检测数据传输或存储过程中的错误。

以下是CRC32算法的基本概述:

CRC32广泛应用于文件传输、存储系统、以太网通信等领域,用于检测数据传输中的错误。由于其简单性和高效性,CRC32在实际应用中被广泛采用。然而,需要注意的是,CRC32主要用于错误检测而非安全性,不适用于对恶意操作的防范。在一些对安全性要求较高的场景中,其他更强大的校验算法可能更为合适。

crc32算法的使用只需要包含<crc.h>头文件,并将程序内的MD5类改为CRC32即可,其他的无任何差异,代码如下所示;

#include <Windows.h>
#include <iostream>

#include <crc.h>
#include <files.h>
#include <hex.h>

using namespace std;
using namespace CryptoPP;

#pragma comment(lib,"cryptlib.lib")

// 计算文件CRC32
string CalCRCByFile(char *pszFileName)
{
	string value;
	CRC32 crc;
	FileSource(pszFileName, true, new HashFilter(crc, new HexEncoder(new StringSink(value))));
	return value;
}

// 计算数据CRC32
string CalCRCByMemory(PBYTE pData, DWORD dwDataSize)
{
	string value;
	CRC32 crc;
	StringSource(pData, dwDataSize, true, new HashFilter(crc, new HexEncoder(new StringSink(value))));
	return value;
}

int main(int argc, char* argv[])
{
	// 定义CRC32类
	CRC32 crc32;

	// 计算文件的MD5
	string crc = CalCRCByFile("d://lyshark.exe");
	printf("crc32 = %s\n", crc.c_str());

	// 计算文件内存的crc
	HANDLE hFile2 = CreateFile("d://lyshark.exe", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);

	// 取文件长度
	DWORD dwFileSize2 = GetFileSize(hFile2, NULL);
	BYTE *pData2 = new BYTE[dwFileSize2];

	// 读文件到内存
	ReadFile(hFile2, pData2, dwFileSize2, NULL, NULL);

	// 计算crc
	string crc2 = CalCRCByMemory(pData2, dwFileSize2);
	printf("crc32 = %s\n", crc2.c_str());

	system("pause");
	return 0;
}

程序运行后将会计算文件的CRC32值,如下图所示;

使用SHA1算法

SHA-1(Secure Hash Algorithm 1)是一种常见的哈希函数,用于生成160位的散列值。与MD5类似,SHA-1也被广泛用于数字签名、数据完整性验证等领域。然而,由于SHA-1存在一些安全性漏洞,特别是对碰撞攻击的脆弱性,因此在对安全性要求较高的应用中,不再推荐使用SHA-1,而是转向使用更安全的哈希算法,如SHA-256或SHA-3。

以下是SHA-1算法的基本概述:

由于SHA-1存在安全性问题,特别是在2017年被证明对碰撞攻击不再是安全的,因此已经不再被推荐用于安全性要求较高的应用。取而代之的是,SHA-256和SHA-3等更安全的哈希算法,它们提供更长的输出长度和更强的抗碰撞能力。

与MD5的计算方法一致,SHA系列计算方式只需引入<sha.h>系列头文件,并使用SHA1 sha1;类进行计算即可,如下代码所示;

#include <Windows.h>
#include <iostream>

#include <sha.h>
#include <files.h>
#include <hex.h>

using namespace std;
using namespace CryptoPP;

#pragma comment(lib,"cryptlib.lib")

// 计算文件SHA1
string CalSHA1ByFile(char *pszFileName)
{
	string value;
	SHA1 sha1;
	FileSource(pszFileName, true, new HashFilter(sha1, new HexEncoder(new StringSink(value))));
	return value;
}

// 计算数据SHA1
string CalSHA1ByMemory(PBYTE pData, DWORD dwDataSize)
{
	string value;
	SHA1 sha1;
	StringSource(pData, dwDataSize, true, new HashFilter(sha1, new HexEncoder(new StringSink(value))));
	return value;
}

int main(int argc, char* argv[])
{
	// 定义SHA类
	SHA1 sha1;

	// 计算文件的sha1
	string sha11 = CalSHA1ByFile("d://lyshark.exe");
	printf("sha1 = %s\n", sha11.c_str());

	// 计算文件内存的sha1
	HANDLE hFile2 = CreateFile("d://lyshark.exe", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);

	// 取文件长度
	DWORD dwFileSize2 = GetFileSize(hFile2, NULL);
	BYTE *pData2 = new BYTE[dwFileSize2];

	// 读文件到内存
	ReadFile(hFile2, pData2, dwFileSize2, NULL, NULL);

	// 计算sha1
	string sha12 = CalSHA1ByMemory(pData2, dwFileSize2);
	printf("sha1 = %s\n", sha12.c_str());

	system("pause");
	return 0;
}

sha1计算结果如下图所示;

使用SHA256算法

SHA-256(Secure Hash Algorithm 256-bit)是SHA-2(Secure Hash Algorithm 2)家族中的一种哈希函数,用于生成256位的散列值。SHA-256是目前广泛应用于各种安全领域的强大哈希算法,包括数字签名、证书签名、数据完整性验证等。SHA-256提供了更高的安全性,相对于之前的SHA-1和MD5来说更为强大。

以下是SHA-256算法的基本概述:

SHA-256相对于SHA-1和MD5提供了更高的抗碰撞能力和更强的安全性,使其成为当前广泛使用的哈希算法之一。然而,随着计算能力的增强,一些专家逐渐倾向于使用更长的哈希算法,如SHA-3,以适应未来更高的安全性需求。

代码调用上与sha1保持一致,Sha256同样只需要少量的更改,只要掌握了这个规律,那么则可以完成其他算法的调用,代码如下所示;

#include <Windows.h>
#include <iostream>

#include <sha.h>
#include <files.h>
#include <hex.h>

using namespace std;
using namespace CryptoPP;

#pragma comment(lib,"cryptlib.lib")

// 计算文件SHA1
string CalSHA1ByFile(char *pszFileName)
{
	string value;
	SHA256 sha256;
	FileSource(pszFileName, true, new HashFilter(sha256, new HexEncoder(new StringSink(value))));
	return value;
}

// 计算数据SHA1
string CalSHA1ByMemory(PBYTE pData, DWORD dwDataSize)
{
	string value;
	SHA256 sha256;
	StringSource(pData, dwDataSize, true, new HashFilter(sha256, new HexEncoder(new StringSink(value))));
	return value;
}

int main(int argc, char* argv[])
{
	// 定义SHA类
	SHA256 sha256;

	// 计算文件的sha256
	string sha11 = CalSHA1ByFile("d://lyshark.exe");
	printf("sha256 = %s\n", sha11.c_str());

	// 计算文件内存的sha256
	HANDLE hFile2 = CreateFile("d://lyshark.exe", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);

	// 取文件长度
	DWORD dwFileSize2 = GetFileSize(hFile2, NULL);
	BYTE *pData2 = new BYTE[dwFileSize2];

	// 读文件到内存
	ReadFile(hFile2, pData2, dwFileSize2, NULL, NULL);

	// 计算sha256
	string sha12 = CalSHA1ByMemory(pData2, dwFileSize2);
	printf("sha256 = %s\n", sha12.c_str());

	system("pause");
	return 0;
}

运行后则可输出文件的sha256值,如下图所示;

以上就是C++通过CryptoPP计算Hash值的过程详解的详细内容,更多关于C++ CryptoPP计算Hash值的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文