Cryptopp进行RSA加密解密

20 篇文章 1 订阅

因最近工作需要,要与一个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=128byte
 
 
        const 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*q
        cout << " p: " << std::hex << p << endl;    //p
        cout << " q: " << std::hex << q << endl;    //q
        cout << " 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; 
 
         
        // 公钥加密 
        // 这里为了验证有效性
        // 直接使用生成的publicKey
        RSAES_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博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值