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.rhkb.cn/news/359547.html

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

相关文章

板凳--------第20章-信号:基本概念1

tlpi_hdr.h头文件使用及设置 liao__ran 于 2020-09-29 15:12:01 发布 阅读量1.6k 收藏 5 点赞数 1 分类专栏&#xff1a; linux系统编程手册 版权 linux系统编程手册 专栏收录该内容 7 篇文章 1 订阅 订阅专栏 使用的头文件&#xff0c;主要如下&#xff1a; ename.c.inc erro…

视频融合共享平台LntonCVS视频监控管理平台技术方案详细介绍

LntonCVS国标视频综合管理平台是一款以视频为核心的智慧物联应用平台。它基于分布式、负载均衡等流媒体技术进行开发&#xff0c;提供广泛兼容、安全可靠、开放共享的视频综合服务。该平台具备多种功能&#xff0c;包括视频直播、录像、回放、检索、云存储、告警上报、语音对讲…

Linux:多线程中的互斥与同步

多线程 线程互斥互斥锁互斥锁实现的原理封装原生线程库封装互斥锁 死锁避免死锁的四种方法 线程同步条件变量 线程互斥 在多线程中&#xff0c;如果存在有一个全局变量&#xff0c;那么这个全局变量会被所有执行流所共享。但是&#xff0c;资源共享就会存在一种问题&#xff1…

基于Pytorch框架构建LeNet-5模型

Pytorch 一、训练模型1.导入必要的库2.设置超参数3.数据预处理4.读取数据 二、定义卷积神经网络1.定义卷积神经网络2.定义学习率3.实例化模型并且移动到GPU4.选择优化器 三、定义调整学习率的函数1.定义调整学习率的函数 四、训练模型1.设置模型为训练模式2.遍历训练数据加载器…

揭秘循环购:消费即收益,如何助力商家月销百万?

大家好&#xff0c;我是吴军&#xff0c;今天要和大家分享一种颠覆性的商业模式——循环购。你是否听说过“消费1000送2000”这样的促销活动&#xff1f;是不是觉得太不可思议&#xff0c;商家岂不是在“送钱”&#xff1f;别急&#xff0c;让我为你揭开这背后的秘密。 循环购&…

RN开发搬砖经验之—“Calculated frame index should never be lower than 0“崩溃问题分析

问题重现 崩溃堆栈&#xff1a; Back traces starts. java.lang.RuntimeException: java.lang.IllegalStateException: Calculated frame index should never be lower than 0at com.facebook.react.animated.NativeAnimatedModule$1.doFrameGuarded(NativeAnimatedModule.ja…

计算机组成原理 | CPU子系统(1)基本概述

基本结构模型 运算与缓存部件 数据寄存部件 PSW不是很清楚 存储器是什么&#xff1f;属于那个结构里&#xff1f; 时序处理部件 cpu是大脑&#xff0c;控制器是神经元 ①通过硬件产生控制信号 ②通过软件产生控制信号 外频&#xff08;系统时钟信号&#xff09;&#xff0c;…

Tesseract-OCR 5.0LSTM训练

准备工作 1.安装tesseract5.0版本 2.配置tesserac环境变量 3.jTessBoxEditor(需要java环境) 很多博客已有详细教程&#xff0c;不再赘述&#xff0c;本文以训练为主 最终文件目录: --tif 需要训练的tif文件 --lstmf 后文会讲到生成的方式 --txt 后文会讲到生成的方式 --box 后文…

【Day02】0基础微信小程序入门-学习笔记

文章目录 模板与配置学习目标WXML 模板语法1.数据绑定&#xff08;类似于 Vue2 &#xff09;2. 事件绑定3. 条件渲染4.列表渲染 WXSS模板样式1. rpx尺寸单位2.样式导入3. 全局样式和局部样式 全局配置1. window2. tabBar 页面配置网络数据请求总结 持续更新~ 模板与配置 学习目…

Databend 开源周报第 149 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持递归公共表…

Nvidia Isaac Sim图编程OmniGraph 入门教程 2024(6)

Nvidia Isaac Sim 入门教程 2024 版权信息 Copyright 2023-2024 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. …

创建一个Django项目

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 本小节我们将开始讲解如何使用Django创建一个项目&#xff0c;步骤如下&#xff1a; &#xff08;1&#xff09;首先在D盘&#xff08;读者可以根据…

Java基础:IO流

目录 一、定义 1.引言 2.分类 &#xff08;1&#xff09;按照流的方向分 &#xff08;2&#xff09;按操作文件的类型分 3.体系结构 二、字节流&#xff08;以操作本地文件为例&#xff09; 1. FileOutputStream 类 &#xff08;1&#xff09;定义 &#xff08;2&am…

使用 Iceberg、Tabular 和 MinIO 构建现代数据架构

现代数据环境需要一种新型的基础架构&#xff0c;即无缝集成结构化和非结构化数据、轻松扩展并支持高效的 AI/ML 工作负载的基础架构。这就是现代数据湖的用武之地&#xff0c;它为您的所有数据需求提供了一个中心枢纽。然而&#xff0c;构建和管理有效的数据湖可能很复杂。 这…

PR模板 | RGB特效视频标题模板Titles | MOGRT

RGB特效视频标题模板mogrt免费下载 4K分辨率&#xff08;38402160&#xff09; 支持任何语言 友好的界面 输入和输出动画 快速渲染 视频教程 免费下载&#xff1a;https://prmuban.com/39055.html 更多pr模板视频素材下载地址&#xff1a;https://prmuban.com

不翻墙安装yolov8环境下的RT-DETR并实现PCB表面缺陷检测

目录 一、新建conda环境二、安装yolov8环境1.克隆安装包2.安装依赖包3.测试模型 任务2&#xff1a;基于RT-DETR实现PKU-PCB表面缺陷检测数据准备 数据增强测试 总结 一、新建conda环境 创建并激活conda环境&#xff1a; 在conda创建一个名为yolov8的新环境&#xff0c;并在其中…

外贸行业 - 收汇日期

“收汇日期”指的是外贸业务中&#xff0c;出口方从进口方收到货款的具体日期。在外贸交易中&#xff0c;特别是使用信用证&#xff08;Letter of Credit, L/C&#xff09;、电汇&#xff08;Telegraphic Transfer, T/T&#xff09;、付款交单&#xff08;Documents against Pa…

《2024云安全资源池 能力指南》

《2024云安全资源池 能力指南》这份报告不仅梳理了云安全资源池的发展历程,还深入探讨了其在当前云计算环境下的重要性和必要性。报告详细分析了云安全资源池的市场需求、技术架构、关键技术以及行业应用案例,为政企用户提供了全面的云安全解决方案。通过资料收集、问卷调研、企…

深入了解 GPT-4 和 ChatGPT 的 API---OpenAI Playground

文章目录 基本概念OpenAI API 提供的可用模型在 OpenAI Playground 中使用 GPT 模型 掌握GPT-4 和 ChatGPT 的 API 的使用方法&#xff0c;以便有效地将它们集成到 Python 应用程序中。首先&#xff0c;需要了解 OpenAI Playground。这将使你在编写代码之前更好地了解模型。接着…

如何将一个web端程序打包成一个pc端程序(exe文件)?

如何将一个Web端程序打包成一个PC端程序&#xff0c;例如一个可执行的EXE文件&#xff0c;是许多开发者常见的需求。下面将详细解释如何使用Nativefier工具将Web端程序打包成PC端程序的具体步骤。 目录 下载并安装Node.js验证Node.js和npm的安装安装Nativefier使用Nativefier打…