Crypto++ 入门

一、简介

Crypto++(也称为CryptoPP、libcrypto++或cryptlib)是一个免费的开源C++库,提供了多种加密方案。它由Wei Dai开发和维护,广泛应用于需要强大加密安全的各种应用程序中。该库提供了广泛的加密算法和协议的实现,包括:

  1. 对称加密算法:AES、DES、3DES、RC2、RC4、RC5、RC6、Blowfish、Twofish等。

  2. 非对称加密算法:RSA、DSA、ElGamal、ECC(椭圆曲线加密)等。

  3. 哈希函数:SHA-1、SHA-2(SHA-224、SHA-256、SHA-384、SHA-512)、MD2、MD4、MD5、RIPEMD-160等。

  4. 消息认证码(MAC):HMAC、CMAC等。

  5. 数字签名算法:DSA、ECDSA、EdDSA等。

  6. 随机数生成器:各种伪随机数生成器和真随机数生成器。

  7. 密码协议:SSL/TLS、SRP(安全远程密码协议)等。

Crypto++的设计目标是提供高性能、高质量的加密算法实现,并且易于集成到C++应用程序中。它是一个跨平台的库,支持多种操作系统,包括Windows、Linux、macOS等。

二、下载

Crypto++下载:

Crypto++ Library 8.9 | Free C++ Class Library of Cryptographic Schemes

或者Tags · weidai11/cryptopp · GitHub

cryptopp-pem下载:

PEM Pack - Crypto++ Wiki ,滚动到页面最下方下载

PEM Pack 是一个消息加密的部分实现,它允许你读取和写入 PEM 编码的密钥和参数,包括加密的私钥。该包额外提供了对 RSA、DSA、EC、ECDSA 密钥以及 Diffie-Hellman 参数的支持。该包包含五个额外的源文件,一个使用 OpenSSL 创建测试密钥的脚本,一个用于测试读取和写入密钥的 C++ 程序,以及一个用于验证由 Crypto++ 写入的密钥的脚本。

最终下载文件如下:

cryptopp-CRYPTOPP_8_7_0.zip

cryptopp-pem-master.zip

三、编译静态库

1、解压cryptopp-CRYPTOPP_8_7_0.zip

再解压cryptopp-pem-master.zip,内容全部拷贝到cryptopp-CRYPTOPP_8_7_0中

2、VS打开cryptest.sln工程

3、往子工程cryptlib中加入pem包

选中cryptlib,右击“Header Files”->添加->现有项:

  • pem.h

  • pem_common.h

右击“Source Files”->添加->现有项:

  • pem_common.cpp

  • pem_read.cpp

  • pem_write.cpp

4、修改属性页-》配置属性-》C/C++ -》代码生成-》运行库 。debug模式选"多线程调试DLL(/MDd) 或者"多线程调试(/MTd)"",release模式选择“多线程DLL(/MD)” 或者"多线程(/MT)"

5、编译生成,右击子工程cryptlib点击“生成”

6、作为SDK发布

创建文件夹cryptopp870,内部创建include文件夹(存放.h文件),创建lib文件(夹存放.lib文件)

cryptopp-CRYPTOPP_8_7_0中所有头文件复制到include中

xxx/cryptopp-CRYPTOPP_8_7_0\x64\Output中的Debug和Release文件夹复制到lib中

 运行库说明:

在 Visual C++ 中,运行库(Runtime Library)有四个主要的选项,它们在编译和链接时使用不同的设置。这些选项主要影响程序的内存管理、异常处理和调试支持等方面。以下是这四个选项的区别:

  1. 多线程 (/MT)

    • 描述:使用静态链接的多线程运行库。

    • 特点

      • 程序在运行时不需要额外的 DLL 支持,因为所有的运行库代码都被静态链接到可执行文件中。

      • 可执行文件较大,因为包含了运行库的所有代码。

      • 适用于发布版本,因为不需要依赖外部 DLL。

    • 适用场景:不需要依赖外部 DLL 的独立应用程序。

  2. 多线程调试 (/MTd)

    • 描述:使用静态链接的多线程调试运行库。

    • 特点

      • /MT 类似,但包含了调试信息,适用于调试版本。

      • 可执行文件较大,因为包含了运行库的所有代码和调试信息。

      • 适用于调试版本,因为可以提供更详细的调试信息。

    • 适用场景:需要详细调试信息的调试版本。

  3. 多线程 DLL (/MD)

    • 描述:使用动态链接的多线程运行库。

    • 特点

      • 程序在运行时需要依赖 msvcrt.dll(Microsoft Visual C++ 运行库 DLL)。

      • 可执行文件较小,因为只包含了程序自身的代码,运行库代码在 msvcrt.dll 中。

      • 适用于发布版本,因为可以减小可执行文件的大小。

    • 适用场景:需要减小可执行文件大小的发布版本。

  4. 多线程调试 DLL (/MDd)

    • 描述:使用动态链接的多线程调试运行库。

    • 特点

      • /MD 类似,但包含了调试信息,适用于调试版本。

      • 程序在运行时需要依赖 msvcrtd.dll(Microsoft Visual C++ 调试运行库 DLL)。

      • 适用于调试版本,因为可以提供更详细的调试信息。

    • 适用场景:需要详细调试信息的调试版本。

总结:

  • /MT/MTd 使用静态链接,适用于不需要依赖外部 DLL 的独立应用程序。

  • /MD/MDd 使用动态链接,适用于需要减小可执行文件大小或依赖外部 DLL 的应用程序。

  • 调试版本通常使用 /MTd/MDd,因为它们包含了调试信息,有助于调试。

在选择运行库选项时,需要根据具体的需求和项目配置来决定使用哪个选项。确保所有相关的库和模块都使用相同的运行库选项,以避免链接错误。

例如,如果你有一个静态库 mylib.lib 是用 /MD 选项编译的,那么任何使用 mylib.lib 的可执行文件或 DLL 也必须使用 /MD 选项进行编译。

四、使用示例

VS配置:

新建一个测试工程,添加依赖库

属性页-》配置属性-》C/C++ -》常规-》附加包含目录,输入头文件路径E:\3rdparty\dist\cryptopp870\include

属性页-》配置属性-》链接器-》常规-》附加库目录,输入lib文件路径E:\3rdparty\dist\cryptopp870\lib\Debug

属性页-》配置属性-》链接器-》输入-》附加依赖项,添加cryptlib.lib

QT配置:


CONFIG(debug, debug|release) {
    QMAKE_CXXFLAGS_DEBUG += /MTd    # 或/MDd
}

CONFIG(release, debug|release) {
    QMAKE_CXXFLAGS_RELEASE += /MT   # 或/MD
}

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/cryptopp870/lib/Release/ -lcryptlib
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/cryptopp870/lib/Debug/ -lcryptlib

INCLUDEPATH += $$PWD/cryptopp870/include
DEPENDPATH += $$PWD/cryptopp870/include

win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/cryptopp870/lib/Release/libcryptlib.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/cryptopp870/lib/Debug/libcryptlib.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/cryptopp870/lib/Release/cryptlib.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/cryptopp870/lib/Debug/cryptlib.lib

4.1、RSA非对称加密

#include <iostream>
#include <string>
#include <rsa.h>
#include <osrng.h>
#include <base64.h>
#include <files.h>
#include <pem.h>using namespace std;
using namespace CryptoPP;class RSAKeyManager {
public:RSAKeyManager() {}void GenerateKeys(int keySize = 2048) {AutoSeededRandomPool rng;privateKey.GenerateRandomWithKeySize(rng, keySize);publicKey = RSA::PublicKey(privateKey);}std::string GetPrivateKeyPEM() const {std::string privateKeyPEM;StringSink privateKeySink(privateKeyPEM);PEM_Save(privateKeySink, privateKey);return privateKeyPEM;}std::string GetPublicKeyPEM() const {std::string publicKeyPEM;StringSink publicKeySink(publicKeyPEM);PEM_Save(publicKeySink, publicKey);return publicKeyPEM;}void SavePrivateKey(const char* filename) const {FileSink file(filename);PEM_Save(file, privateKey);}void SavePublicKey(const char* filename) const {FileSink file(filename);PEM_Save(file, publicKey);}void LoadPrivateKey(const char* filename) {FileSource file(filename, true);PEM_Load(file, privateKey);}void LoadPublicKey(const char* filename) {FileSource file(filename, true);PEM_Load(file, publicKey);}void LoadPrivateKeyFromString(const std::string& privateKeyPEM) {StringSource source(privateKeyPEM, true);PEM_Load(source, privateKey);}void LoadPublicKeyFromString(const std::string& publicKeyPEM) {StringSource source(publicKeyPEM, true);PEM_Load(source, publicKey);}std::string Encrypt(const std::string& message) const {AutoSeededRandomPool rng;std::string encrypted;RSAES_OAEP_SHA_Encryptor encryptor(publicKey);StringSource(message, true,new PK_EncryptorFilter(rng, encryptor,new StringSink(encrypted)));return encrypted;}std::string Decrypt(const std::string& encrypted) const {AutoSeededRandomPool rng;std::string decrypted;RSAES_OAEP_SHA_Decryptor decryptor(privateKey);StringSource(encrypted, true,new PK_DecryptorFilter(rng, decryptor,new StringSink(decrypted)));return decrypted;}private:RSA::PrivateKey privateKey;RSA::PublicKey publicKey;
};int main() {try {RSAKeyManager keyManager;// 生成密钥对keyManager.GenerateKeys();// 将私钥和公钥转换为PEM格式std::string privateKeyPEM = keyManager.GetPrivateKeyPEM();std::cout << "RSA Private Key:" << std::endl;std::cout << privateKeyPEM << std::endl;std::string publicKeyPEM = keyManager.GetPublicKeyPEM();std::cout << "RSA Public Key:" << std::endl;std::cout << publicKeyPEM << std::endl;// 从字符串加载密钥对RSAKeyManager loadedKeyManager;loadedKeyManager.LoadPrivateKeyFromString(privateKeyPEM);loadedKeyManager.LoadPublicKeyFromString(publicKeyPEM);// 加密string message = "Hello, World!";string encrypted = loadedKeyManager.Encrypt(message);// 解密string decrypted = loadedKeyManager.Decrypt(encrypted);// 输出结果cout << "Original message: " << message << endl;cout << "Encrypted message: " << encrypted << endl;cout << "Decrypted message: " << decrypted << endl;}catch (const Exception& e) {cout << "Crypto++ exception: " << e.what() << endl;}catch (const std::exception& e) {cout << "Standard exception: " << e.what() << endl;}catch (...) {cout << "Unknown exception" << endl;}return 0;
}

4.2、RSA签名

生成密钥对、签名数据以及验证签名

#include <iostream>
#include <string>
#include <rsa.h>
#include <osrng.h>
#include <base64.h>
#include <files.h>
#include <pem.h>
#include <sha.h>
#include <hex.h>
#include <pssr.h>using namespace std;
using namespace CryptoPP;void GenerateKeyPair(RSA::PrivateKey& privateKey, RSA::PublicKey& publicKey) {AutoSeededRandomPool rng;privateKey.GenerateRandomWithKeySize(rng, 2048);publicKey = RSA::PublicKey(privateKey);
}bool SignMessage(const string& message, const RSA::PrivateKey& privateKey, string &signature) {try{AutoSeededRandomPool rng;RSASS<PSS, SHA256>::Signer signer(privateKey);StringSource(message, true,new SignerFilter(rng, signer,new StringSink(signature)));}catch (const Exception& e){cout << "Sign exception: " << e.what() << endl;return false;}return true;
}bool VerifyMessage(const string& message, const string& signature, const RSA::PublicKey& publicKey) {try {RSASS<PSS, SHA256>::Verifier verifier(publicKey);/* 解签使用内容+签名 */StringSource ss(message + signature , true,new SignatureVerificationFilter(verifier,NULL,SignatureVerificationFilter::THROW_EXCEPTION | SignatureVerificationFilter::PUT_MESSAGE));}catch (const Exception& e) {cout << "Verifier exception: " << e.what() << endl;return false;}return true;
}struct LicenseData {string message = "2024/6/19, 2024/7/19";string signature;   /* 数字签名,验证数据是否被修改 */string publicKey;   /* 公钥 */
};int main() {try {RSA::PrivateKey privateKey;RSA::PublicKey publicKey;// 生成密钥对GenerateKeyPair(privateKey, publicKey);// 要签名的消息string message = "Hello, World!";// 签名消息string signature;bool b = SignMessage(message, privateKey, signature);cout << "signature:" << b << endl << signature << endl;// 验证签名b= VerifyMessage(message, signature, publicKey);if (b) {cout << "Signature is valid." << endl;}else {cout << "Signature is invalid." << endl;}}catch (const Exception& e) {cout << "Crypto++ exception: " << e.what() << endl;}catch (const std::exception& e) {cout << "Standard exception: " << e.what() << endl;}catch (...) {cout << "Unknown exception" << endl;}return 0;
}

4.3、 Base64 编码和解码

#include <iostream>
#include <string>#include <rsa.h>
#include <osrng.h>
#include <base64.h>
#include <files.h>
#include <pem.h>using namespace std;
using namespace CryptoPP;class Base64 {
public:static std::string encode(const std::string& data) {std::string encoded;CryptoPP::Base64Encoder encoder;encoder.Attach(new CryptoPP::StringSink(encoded));encoder.Put((const byte*)data.data(), data.size());encoder.MessageEnd();return encoded;}static std::string decode(const std::string& encoded) {std::string decoded;CryptoPP::Base64Decoder decoder;decoder.Attach(new CryptoPP::StringSink(decoded));decoder.Put((const byte*)encoded.data(), encoded.size());decoder.MessageEnd();return decoded;}
};int main()
{try {// 原始数据std::string data = "Hello, World!";// Base64 编码std::string encoded = Base64::encode(data);std::cout << "Encoded data: " << encoded << std::endl;// Base64 解码std::string decoded = Base64::decode(encoded);std::cout << "Decoded data: " << decoded << std::endl;}catch (const Exception& e) {cout << "Crypto++ exception: " << e.what() << endl;}catch (const std::exception& e) {cout << "Standard exception: " << e.what() << endl;}catch (...) {cout << "Unknown exception" << endl;}return 0;
}

4.4、AES对称加密

#include <iostream>
#include <string>
#include <aes.h>
#include <modes.h>
#include <filters.h>
#include <hex.h>
#include <osrng.h>using namespace std;
using namespace CryptoPP;class AESCipher {
public:AESCipher(const string& key, const string& iv) : key(key), iv(iv) {}string Encrypt(const string& plainText) {string cipherText;try {CBC_Mode<AES>::Encryption encryptor;encryptor.SetKeyWithIV((byte*)key.data(), key.size(), (byte*)iv.data());StringSource(plainText, true,new StreamTransformationFilter(encryptor,new StringSink(cipherText)));}catch (const Exception& e) {cerr << "Encryption error: " << e.what() << endl;}return cipherText;}string Decrypt(const string& cipherText) {string plainText;try {CBC_Mode<AES>::Decryption decryptor;decryptor.SetKeyWithIV((byte*)key.data(), key.size(), (byte*)iv.data());StringSource(cipherText, true,new StreamTransformationFilter(decryptor,new StringSink(plainText)));}catch (const Exception& e) {cerr << "Decryption error: " << e.what() << endl;}return plainText;}private:string key;string iv;
};int main() {// 生成随机的密钥和初始化向量(IV)AutoSeededRandomPool rng;byte key[AES::DEFAULT_KEYLENGTH];byte iv[AES::BLOCKSIZE];rng.GenerateBlock(key, sizeof(key));rng.GenerateBlock(iv, sizeof(iv));string keyStr(reinterpret_cast<char*>(key), sizeof(key));string ivStr(reinterpret_cast<char*>(iv), sizeof(iv));AESCipher aes(keyStr, ivStr);string plainText = "Hello, World!";string encryptedText = aes.Encrypt(plainText);string decryptedText = aes.Decrypt(encryptedText);cout << "Original Text: " << plainText << endl;cout << "Encrypted Text: " << encryptedText << endl;cout << "Decrypted Text: " << decryptedText << endl;return 0;
}

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

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

相关文章

Spring循环依赖问题——从源码画流程图

文章目录 关键代码相关知识为什么要使用二级缓存为什么要使用三级缓存只使用两个缓存的问题不能解决构造器循环依赖为什么多例bean不能解决循环依赖问题初始化后代理对象赋值给原始对象解决循环依赖SpringBoot开启循环依赖 循环依赖 在线流程图 关键代码 从缓存中查询getSingl…

【贪心算法初级训练】在花坛上是否能种下n朵花、碰撞后剩余的行星

1、在花坛上是否能种下n多花 一个很长的花坛&#xff0c;一部分地已经种植了花&#xff0c;另一部分却没有&#xff0c;花不能种植在相邻的地块上否则它们会争夺水源&#xff0c;两者都会死去。给你一个整数数组表示花坛&#xff0c;由若干个0和1组成&#xff0c;0表示没种植花…

51单片机STC89C52RC——7.1 串口通信

目的/效果 实现单片机串口与电脑串口工具进行数据通讯&#xff0c; 1&#xff1a;设备向电脑串口发送HEX 2&#xff1a;让电脑串口工具控制单片机LED亮灭。同时让单片机反馈控制的结果。 一&#xff0c;STC单片机模块 二&#xff0c;串口通讯 2.1 串行通信与并行通信 &…

axios全局封装AbortController取消重复请求

为什么&#xff1f; 问题&#xff1a;为什么axios要配置AbortController&#xff1f;防抖节流不行吗&#xff1f; 分析&#xff1a; 防抖节流本质上是用延时器来操作请求的。防抖是判断延时器是否存在&#xff0c;如果存在&#xff0c;清除延时器&#xff0c;重新开启一个延…

win10改远程桌面端口,Windows 10 修改远程桌面端口号的专业指南

在Windows 10系统中&#xff0c;远程桌面&#xff08;Remote Desktop&#xff09;功能允许用户从一台计算机远程访问和控制另一台计算机。为了增加远程连接的安全性&#xff0c;减少潜在的安全风险&#xff0c;修改默认的远程桌面端口号是一个常见的安全措施。以下是在Windows …

k8s学习--YAML资源清单文件托管服务nginx

文章目录 前言应用环境具体实现步骤1.安装源码nginx及相关模块2.修改nginx配置文件3.启动验证4.测试 总结 前言 nginx 是一个开源的高性能 HTTP 和反向代理服务器&#xff0c;也是一个 IMAP/POP3/SMTP 代理服务器。在容器和 Kubernetes 的背景下&#xff0c;nginx 经常被用作静…

决策树算法原理

目录 一&#xff1a;介绍 二&#xff1a;算法原理 1.熵和信息熵 2.信息增益 三决策树分裂指标 1.信息熵分裂&#xff1a; 2.Gini系数&#xff08;CART&#xff09; 3.信息增益率 一&#xff1a;介绍 决策树( Decision Tree) 又称为判定树&#xff0c;是数据挖掘技术中的…

你如何看待市场波动性的?

实际上&#xff0c;波动性并不总是负面的&#xff0c;它有时也孕育着快速获利的机会。 对于长期投资者而言&#xff0c;市场波动&#xff08;尤其与熊市相伴时&#xff09;往往是一个优势。它允许投资者拓展并多样化投资组合&#xff0c;以较低的价格购入投资工具&#xff0c;…

【嵌入式Linux】<总览> 多进程(更新中)

文章目录 前言 一、进程的概念与结构 1. 相关概念 2. 内核区中的进程结构 3. 进程的状态 4. 获取进程ID函数 二、进程创建 1. fork和vfork函数 2. 额外注意点 3. 构建进程链 4.构建进程扇 三、进程终止 1. C程序的启动过程 2. 进程终止方式 四、特殊的进程 1. 僵…

免费体验软件开发生产线 CodeArts

软件开发生产线 CodeArts 一站式、全流程、安全可信的软件开发生产线&#xff0c;开箱即用&#xff0c;内置华为多年研发最佳实践&#xff0c;助力效能倍增和数字化转型 免费试用体验版套餐&#xff0c;50人内免费试用 功能特性 Scrum和看板需求模型 代码托管 代码检查&am…

GIS开发如何高质量就业?这几点是关键!

高质量就业&#xff0c;包含薪资和其他福利待遇&#xff0c;在讨论如何高质量就业之前&#xff0c;我们先来看下GIS开发岗位的前景、薪资水平如何&#xff1f;最后讨论一下GIS开发工程师到底需要学习哪些技术&#xff1f; 01 GIS开发岗位呈持续上升趋势 从GIS开发岗位趋势也可…

Java知识点整理 11— 后端 Spring Boot 万用初始化模板使用

一. 模块简介 annotation&#xff1a;自定义注解aop&#xff1a;请求日志和权限校验common&#xff1a;通用类config&#xff1a;配置类constant&#xff1a;常量 controller&#xff1a;控制层esdao&#xff1a;方便操作ESexception&#xff1a;异常类job&#xff1a;定时任务…

Facebook广告投放的6个误区,老手也会犯

一、没有目标 无论是投放哪种产品&#xff0c;我们始终都需要明确&#xff0c;广告的目标是什么。 因为Facebook广告的形式和类型&#xff0c;也经常会有变化&#xff0c;例如近期Facebook推出的360视频广告&#xff0c;以及之后即将推出的LIVE&#xff0c;Mid-Roll视频插播广…

美国电商选品、大促、趋势、案例,掌慧科技首期NewsBreak沙龙干货满满

今年第一季度&#xff0c;美国电商销售额达到了2681.2亿美元&#xff0c;相较上一年同期的2471.8亿美元增长8.5%。同时&#xff0c;该季度美国电商销售额在零售业总销售额中的占比为22.2%&#xff0c;高于上一年同期的21.2%。美国在2023年下半年通胀得到良好控制&#xff0c;20…

CleanMyMac2024破解版下载链接!你的Mac清洁利器!

嘿&#xff0c;亲爱的朋友们&#xff0c;今天我要跟大家分享一款我最近超级依赖的电脑清理神器—CleanMyMac2024破解版&#xff01;如果你还在为电脑运行缓慢、存储空间不够而烦恼&#xff0c;那你一定不能错过它&#xff01; &#x1f525; 为什么选择CleanMyMac2024破解版&am…

声波的种类

声波可以根据不同的特性进行分类&#xff0c;主要包括频率和传播方式两个方面&#xff1a; ### 按频率分类&#xff1a; 1. **次声波**&#xff1a;频率低于20Hz的机械波&#xff0c;这类波通常不能被人耳感知。 2. **可闻声波**&#xff1a;频率在20Hz至20kHz之间的机械波&am…

C++ | Leetcode C++题解之第160题相交链表

题目&#xff1a; 题解&#xff1a; class Solution { public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {if (headA nullptr || headB nullptr) {return nullptr;}ListNode *pA headA, *pB headB;while (pA ! pB) {pA pA nullptr ? headB : p…

【fiddler】fiddler抓取websocket

1.先了解websocket流 下载4.5版本以上的fiddler 如图所示&#xff1a;在rules--customize rules 里面插入以下代码&#xff1a; static function OnWebSocketMessage(oMsg: WebSocketMessage) { // Log Message to the LOG tab FiddlerApplication.Log.LogString(oMsg.ToStr…

鸿蒙开发下拉选项框在表单递交的处理

下拉选项框 <select name"identity"><option value"0">顾 客</option><option value"1">行 政</option><option value"2" >保 洁</option></select>在表单数据中没有找到identit…

Win11 Docker Desktop下部署springboot jar

1.将springboot程序使用maven package打包出jar。 2.创建dockerfile&#xff0c;为了本地打包时方便&#xff0c;这里的dockerfile有小变动。 # Docker Desktop下部署springboot jar FROM openjdk:8 VOLUME /tmp EXPOSE 8601 ARG JAR_FILEtarget/webflux-hello-0.0.1-SNAPSHO…