Cryptopp进行RSA加密解密

news/2024/9/25 8:28:22/

因最近工作需要,要与一个java服务器进行部分数据交互,其中用户名、密码的加密方式为RSA非对称加密,故研究了一下使用Cryptopp库进行RSA的公钥加密。


搜索了很多资料,其中觉得十分有用的一句话是:

客户端使用RSA加密通常要跟服务器端进行交互,服务器端多为java、.net等编写,在java和.net语言中的RSA加密算法通常使用的是PKCS标准进行加密解密,而cryptopp的实例程序中使用的是SHA1标准,所以如果要跟java的RSA加密算法可以互相解密密文,则cryptopp中也需要以PKCS标准进行加密解密,具体方法是将RSAES_OAEP_SHA_Decryptor/RSAES_OAEP_SHA_Encryptor替换为RSAES_PKCS1v15_Decryptor/RSAES_PKCS1v15_Encryptor


废话不多说,下面是我最终使用的代码:

首先需要知道base64的公钥,保存为rsa-base64-public.key放到程序根目录下。

下面就是从.key文件读取公钥,进而对字符串进行RSA加密,以及转base64的过程:

#include <hex.h>
#include <oids.h>
#include <assert.h>
#include <pkcspad.h>
#include <randpool.h>#include <rsa.h>
using CryptoPP::RSA;
using CryptoPP::InvertibleRSAFunction;
using CryptoPP::RSAES_OAEP_SHA_Encryptor;
using CryptoPP::RSAES_PKCS1v15_Encryptor;
using CryptoPP::RSAES_OAEP_SHA_Decryptor;#include "sha.h"
using CryptoPP::SHA1;#include <filters.h>
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::PK_EncryptorFilter;
using CryptoPP::PK_DecryptorFilter;#include <files.h>
using CryptoPP::FileSink;
using CryptoPP::FileSource;#include <osrng.h>
using CryptoPP::AutoSeededRandomPool;#include "SecBlock.h"
using CryptoPP::SecByteBlock;#include "cryptlib.h"
using CryptoPP::Exception;
using CryptoPP::DecodingResult;
using CryptoPP::PrivateKey;
using CryptoPP::PublicKey;
using CryptoPP::BufferedTransformation;#include <string>
using std::string;#include <stdexcept>
using std::runtime_error;#include <exception>
using std::exception;#include <iostream>
using std::cout;
using std::cerr;
using std::endl;#include <queue.h>
using CryptoPP::ByteQueue;#include <integer.h>
using CryptoPP::Integer;#include <base64.h>
using CryptoPP::Base64Encoder;
using CryptoPP::Base64Decoder;void Load(const string& filename, BufferedTransformation& bt)
{FileSource file(filename.c_str(), true /*pumpAll*/);file.TransferTo(bt);bt.MessageEnd();
}void LoadBase64(const string& filename, BufferedTransformation& bt)
{Base64Decoder decoder;Load(filename,decoder);decoder.CopyTo(bt);bt.MessageEnd();
}void LoadBase64PublicKey(const string& filename, PublicKey& key)
{ByteQueue queue;LoadBase64(filename, queue);key.Load(queue);
}QString LoginDlg::getRSAString(const QString &orgStr)
{RSA::PublicKey  public_Key;LoadBase64PublicKey("rsa-base64-public.key", public_Key);string text = orgStr.toStdString();string encrypted_text;// 创建随机数生成器AutoSeededRandomPool rng;// 创建加密器RSAES_OAEP_SHA_Encryptor                        encryptor1(public_Key);RSAES_PKCS1v15_Encryptor                        encryptor2(public_Key);CryptoPP::RSAES<CryptoPP::PKCS1v15>::Encryptor  encryptor3(public_Key);// 加密文本| 上面有三种,下面使用第二种与java对接OK!std::string cipherText;StringSource ss(text, true,new PK_EncryptorFilter(rng, encryptor2,new StringSink(cipherText)));// 输出加密后的文本(Base64 编码)std::string encoded;StringSource ss2(cipherText, true,new Base64Encoder(new StringSink(encoded)));QString base64Str = QString::fromStdString(encoded).remove("\n");return base64Str;
}

下面是更多封装的版本: 

#include <hex.h>
#include <oids.h>
#include <assert.h>
#include <pkcspad.h>
#include <randpool.h>#include <rsa.h>
using CryptoPP::RSA;
using CryptoPP::InvertibleRSAFunction;
using CryptoPP::RSAES_OAEP_SHA_Encryptor;
using CryptoPP::RSAES_PKCS1v15_Encryptor;
using CryptoPP::RSAES_OAEP_SHA_Decryptor;#include "sha.h"
using CryptoPP::SHA1;#include <filters.h>
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::PK_EncryptorFilter;
using CryptoPP::PK_DecryptorFilter;#include <files.h>
using CryptoPP::FileSink;
using CryptoPP::FileSource;#include <osrng.h>
using CryptoPP::AutoSeededRandomPool;#include "SecBlock.h"
using CryptoPP::SecByteBlock;#include "cryptlib.h"
using CryptoPP::Exception;
using CryptoPP::DecodingResult;
using CryptoPP::PrivateKey;
using CryptoPP::PublicKey;
using CryptoPP::BufferedTransformation;#include <string>
using std::string;#include <stdexcept>
using std::runtime_error;#include <exception>
using std::exception;#include <iostream>
using std::cout;
using std::cerr;
using std::endl;#include <queue.h>
using CryptoPP::ByteQueue;#include <integer.h>
using CryptoPP::Integer;#include <base64.h>
using CryptoPP::Base64Encoder;
using CryptoPP::Base64Decoder;//保存公钥和私钥
void SavePrivateKey(const string& filename, const PrivateKey& key);
void SavePublicKey(const string& filename, const PublicKey& key);//base64编码
void SaveBase64PrivateKey(const string& filename, const PrivateKey& key);
void SaveBase64PublicKey(const string& filename, const PublicKey& key);//保存
void Save(const string& filename, const BufferedTransformation& bt);
void SaveBase64(const string& filename, const BufferedTransformation& bt);//读取key
void LoadPrivateKey(const string& filename, PrivateKey& key);
void LoadPublicKey(const string& filename, PublicKey& key);void LoadBase64PrivateKey(const string& filename, PrivateKey& key);
void LoadBase64PublicKey(const string& filename, PublicKey& key);void LoadBase64(const string& filename, BufferedTransformation& bt);
void Load(const string& filename, BufferedTransformation& bt);int main(int argc, char* argv[])
{try{// 生成私钥和公钥 AutoSeededRandomPool rng;InvertibleRSAFunction parameters;parameters.GenerateRandomWithKeySize( rng, 1024 ); //生成1024bit密钥,即n=128byteconst Integer& n = parameters.GetModulus();const Integer& p = parameters.GetPrime1();const Integer& q = parameters.GetPrime2();const Integer& d = parameters.GetPrivateExponent();const Integer& e = parameters.GetPublicExponent();cout << "RSA Parameters:" << endl;cout << " n: " << std::hex << n << endl;    //n=p*qcout << " p: " << std::hex << p << endl;    //pcout << " q: " << std::hex << q << endl;    //qcout << " d: " << std::hex << d << endl;    cout << " e: " << std::hex << e << endl;    //e默认是17,原因不明cout << endl; //生成公钥和私钥RSA::PrivateKey privateKey( parameters );//私钥用于加密(n,d)RSA::PublicKey  publicKey( parameters ); //公钥用于解密(n,e)//默认使用ASN.1 DER编码//SavePrivateKey("rsa-private.key", privateKey);//SavePublicKey("rsa-public.key", publicKey);//输出privateKey//ByteQueue queue;//privateKey.Save(queue);//保存private_key到char[]中,//注意char[]长度要足够//注意这里privateKey不仅包括n和d//是使用ASN.1 DER编码的字符数组//char private_key_der_string[1024];//size_t size = queue.MaxRetrievable();//queue.Get((byte*)private_key_der_string,size);//for(int i=0;i<1024;i++)//  cout << std::hex << ((int)private_key_der_string[i]&0xff) << " ";//保存private_key到string中,//注意要预留string size//string private_key_der_string;//size_t size = queue.MaxRetrievable();//if(size)//{//  private_key_der_string.resize(size);        //  queue.Get((byte*)private_key_der_string.data(), //              private_key_der_string.size());//} //for(auto it = private_key_der_string.begin();//      it!=private_key_der_string.end(); it++)//  cout<< std::hex << (*it & 0xff);     //16进制输出char自动转int,需要截断字节//cout << endl << endl;//StringSource参数:(原始字符串, 长度, 变换方式filter)//使用filter将char[]转存为base64编码//string bs64_private_key;//StringSource ss(private_key_der_string, true,//  new Base64Encoder(  //base64编码器//      new StringSink(bs64_private_key)    //保存到bs64_private_key//      ) //  ); //cout << bs64_private_key << endl;//保存base64 key到文件SaveBase64PrivateKey("rsa-base64-private.key", privateKey);SaveBase64PublicKey("rsa-base64-public.key", publicKey);////=================分割线=======================//////读取bs64保存的privateKey和publicKey//RSA::PrivateKey private_Key;RSA::PublicKey  public_Key;//LoadBase64PrivateKey("rsa-base64-private.key", private_Key);LoadBase64PublicKey("rsa-base64-public.key", public_Key);string text= "你好世界", encrypted_text, decrypted_text; // 公钥加密 // 这里为了验证有效性// 直接使用生成的publicKeyRSAES_OAEP_SHA_Encryptor encryptor( public_Key );StringSource( text, true,new PK_EncryptorFilter( rng, encryptor,new StringSink( encrypted_text )) ); // 私钥解密 RSAES_OAEP_SHA_Decryptor decryptor( privateKey );StringSource( encrypted_text, true,new PK_DecryptorFilter( rng, decryptor,new StringSink( decrypted_text ))); cout << decrypted_text << endl;//assert( text == decrypted_text );}catch( CryptoPP::Exception& e ){cerr << "Caught Exception..." << endl;cerr << e.what() << endl;}system("pause");return 0;
}void Save(const string& filename, const BufferedTransformation& bt)
{FileSink file(filename.c_str());bt.CopyTo(file);file.MessageEnd();
}void SaveBase64(const string& filename, const BufferedTransformation& bt)
{Base64Encoder encoder;bt.CopyTo(encoder);encoder.MessageEnd();Save(filename, encoder);
}void SavePrivateKey(const string& filename, const PrivateKey& key)
{ByteQueue queue;key.Save(queue);Save(filename, queue);
}void SavePublicKey(const string& filename, const PublicKey& key)
{ByteQueue queue;key.Save(queue);Save(filename, queue);
}void SaveBase64PrivateKey(const string& filename, const PrivateKey& key)
{ByteQueue queue;key.Save(queue);SaveBase64(filename, queue);
}void SaveBase64PublicKey(const string& filename, const PublicKey& key)
{ByteQueue queue;key.Save(queue);SaveBase64(filename, queue);
}void LoadPrivateKey(const string& filename, PrivateKey& key)
{ByteQueue queue;Load(filename, queue);key.Load(queue);    
}void LoadPublicKey(const string& filename, PublicKey& key)
{ByteQueue queue;Load(filename, queue);key.Load(queue);    
}void Load(const string& filename, BufferedTransformation& bt)
{FileSource file(filename.c_str(), true /*pumpAll*/);file.TransferTo(bt);bt.MessageEnd();
}void LoadBase64(const string& filename, BufferedTransformation& bt)
{Base64Decoder decoder;Load(filename,decoder);decoder.CopyTo(bt);bt.MessageEnd();
}void LoadBase64PrivateKey(const string& filename, PrivateKey& key)
{ByteQueue queue;LoadBase64(filename, queue);key.Load(queue);    
}void LoadBase64PublicKey(const string& filename, PublicKey& key)
{ByteQueue queue;LoadBase64(filename, queue);key.Load(queue);    
}

在此做一个记录,方便日后自己查找,以及希望能够帮助大家!

Cryptopp库可以通过我的CSDN下载进行下载,同时也有另一篇文章介绍MD5的相关操作!

Qt使用Cryptopp生成HMAC-MD5_cryptopp md5-CSDN博客


http://www.ppmy.cn/news/1530209.html

相关文章

C++语言桌面应用开发GTK3 Gtkmm3 Glade

文章目录 Gikmm 简介安装 Gtkmm安装 GTK安装 Gladedemo.glade 文件完整示例 demo.cpp编译运行GTK 主题推荐主题 Gikmm 简介 Gtkmm 是一个用于创建图形用户界面&#xff08;GUI&#xff09;的 C 库&#xff0c;它是基于流行的 GTK 库的。GTK 是一个跨平台的 GUI 工具包&#xff…

洛谷P2571.传送带

洛谷P2571.传送带 三分模板题 用于单峰函数求极值 一定可以将答案路径分成三段即AE - EF - FD (E和A可能重复&#xff0c;F和D可能重合) E在线段AB上&#xff0c;F在线段CD上 因为有两个不定点EF&#xff0c;因此假设E为参数&#xff0c;三分求F的位置再外层三分求E的位置 …

240924-Windows映射网络驱动器的方法

在Windows上加载网络盘&#xff08;映射网络驱动器&#xff09;可以通过以下步骤完成&#xff1a; 方法一&#xff1a;通过文件资源管理器 打开文件资源管理器&#xff1a; 可以按 Win E 打开&#xff0c;或者直接点击任务栏上的文件资源管理器图标。 点击“此电脑”&#x…

Java服务端服务发现:Nacos与Eureka的高级特性

Java服务端服务发现&#xff1a;Nacos与Eureka的高级特性 大家好&#xff0c;我是微赚淘客返利系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在微服务架构中&#xff0c;服务发现是实现服务间通信的关键机制。Nacos和Eureka是两种…

【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL18

实现3-8译码器① 描述 下表是74HC138译码器的功能表. E3 E2_n E1_n A2 A1 A0 Y0_n Y1_n Y2_n Y3_n Y4_n Y5_n Y6_n Y7_n x 1 x x x x 1 1 1 1 1 1 1 1 x x 1 x x x 1 1 1 1 1 1 1 1 0 x x x x x 1 1 1 1 1 1 1 1 1 …

鸿蒙OpenHarmony【小型系统内核(用户态启动)】子系统开发

用户态启动 用户态根进程启动 根进程是系统第一个用户态进程&#xff0c;进程ID为1&#xff0c;它是所有用户态进程的祖先。 图1 进程树示意图 根进程的启动过程 使用链接脚本将如下init启动代码放置到系统镜像指定位置。 #define LITE_USER_SEC_ENTRY __attribute__((s…

Ansible部署与应用基础

由于互联网的快速发展导致产品更新换代速度逐步增长&#xff0c;运维人员每天都要进行大量的维护操作&#xff0c;按照传统方式进行维护使得工作效率低下。这时部署自动化运维就 可以尽可能安全、高效的完成这些工作。 一、Ansible概述 1.什么是Ansible Ansible 是基于 Pytho…

Windows环境下Node.js多版本切换的实用指南

Web开发和全栈开发中&#xff0c;Node.js已成为不可或缺的工具之一。然而&#xff0c;随着项目的多样化和技术栈的更新迭代&#xff0c;我们可能需要同时管理多个Node.js版本以满足不同项目的需求。在Windows环境下&#xff0c;如何高效地切换这些版本成为了一个关键问题。简单…