基于cyptopp库的rsa加解密详解

本文转载自博客:http://blog.csdn.net/u010718606/article/details/52328592

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

基于cyptopp库的rsa加解密详解

原创 2016年08月26日 17:21:14

编译Cryptopp

编译过程没有什么特别,需要注意的是,如果使用dll版本的库,只包含IPS认证的算法,而编译静态链接库则包含全部算法,具体参考[1,2]。

  • cryptopp - This builds the DLL. Please note that if you wish to use Crypto++ as a FIPS validated module, you must use a pre-built DLL that has undergone the FIPS validation process instead of building your own.
  • dlltest - This builds a sample application that only uses the DLL.
  • cryptest Non-DLL-Import Configuration - This builds the full static library along with a full test driver.
  • cryptest DLL-Import Configuration - This builds a static library containing only algorithms not in the DLL, along with a full test driver that uses both the DLL and the static library.

本人编译的lib库大小为50多M。

RSA算法介绍

关于rsa算法的介绍可以参考阮一峰的两篇两篇博文,在文末[3,4]以列出。
在RSA算法中有几个需要注意的点,我罗列一下:

非对称加密:对称加密算法在加密和解密时使用的是同一个秘钥;而非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,进行加密)和私有密钥(private key,用于解密)。
RSA用途:RSA加密算法除了用于少量数据加密之外,最主要的应用就是数字签名。
数字签名:包含3个步骤。详见[5]:
  • 待发送消息(message)利用Hash函数,生成信息的摘要;
  • 私钥加密摘要,生成”数字签名”(signature)
  • 发送message+signature
  • 公钥解密签名
  • message重新生成摘要,与发送过来的摘要进行比较
公钥和私钥:公钥和私钥是成对的,它们互相解密。公钥加密,私钥解密。私钥数字签名,公钥验证。
RSA秘钥长度:cyptopp至少要求秘钥长度为1024;秘钥长度即为n值大小,即n=128byte
明文长度:一般应小于等于密钥长度(Bytes)-11,末尾采用填充。
解决长度限制:主要有2种方式
  • 先用对称加密算法(AES/DES等)加密数据,然后用RSA公钥加密对称加密密钥,用RSA的私钥解密得到对称加密的密钥,然后完成反向操作得到明文。
  • 分段进行RSA加密

示例代码

加密与解密

#include "rsa.h"
using CryptoPP::RSA;
using CryptoPP::InvertibleRSAFunction;
using CryptoPP::RSAES_OAEP_SHA_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;


#include <assert.h>


////////////////////////////////////////////////
//保存公钥和私钥
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);    
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318

注意:
下面是生成的一组秘钥值,30开头的值是密钥的保存形式。查看源代码,可以发现其内部是使用默认使用ASN.1 DER编码进行持久化。
这里写图片描述
利用dumpans1,可以对DER编码进行解释。图片中的红框部分为密钥种的N值部分。
这里写图片描述

数字签名

#include "stdafx.h"

#include "rsa.h"
using CryptoPP::RSA;
using CryptoPP::RSASS;
using CryptoPP::InvertibleRSAFunction;

#include "pssr.h"
using CryptoPP::PSS;

#include "sha.h"
using CryptoPP::SHA1;

#include "files.h"
using CryptoPP::FileSink;
using CryptoPP::FileSource;

#include "filters.h"
using CryptoPP::SignerFilter;
using CryptoPP::SignatureVerificationFilter;
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::Integer;

#include "osrng.h"
using CryptoPP::AutoSeededRandomPool;

#include "SecBlock.h"
using CryptoPP::SecByteBlock;

#include <string>
using std::string;

#include <iostream>
using std::cout;
using std::endl;

#include <sha.h>
using CryptoPP::SHA;


int main(int argc, char* argv[])
{
    try
    {
        ////////////////////////////////////////////////
        // 伪随机数生成器
        AutoSeededRandomPool rng;

        InvertibleRSAFunction parameters;
        parameters.GenerateRandomWithKeySize( rng, 1024 );

        ///////////////////////////////////////
        // 生成私钥和公钥
        RSA::PrivateKey privateKey( parameters );       //(n,e)
        RSA::PublicKey  publicKey( parameters );        //(n,d)

        // 发送消息
        string message = "Hello,world!";
        string signature;

        // 生成摘要
        SHA hash;
        //byte digest[SHA::DIGESTSIZE];
        string digest;
        digest.resize(SHA::DIGESTSIZE);
        hash.CalculateDigest((byte*)digest.data(),(byte*)message.data(),message.length());

        // 输出摘要
        for(auto it = digest.begin(); it!=digest.end(); it++)
            cout<< std::hex << (*it & 0xff);     //16进制输出char自动转int,需要截断字节
        cout << endl << endl;

        ////////////////////////////////////////////////
        // 利用私钥进行签名
        RSASS<PSS, SHA1>::Signer signer( privateKey );
        StringSource( digest, true,
            new SignerFilter( rng, signer,
                new StringSink( signature )
            ) // SignerFilter
        ); // StringSource

        // 输出摘要加密结果
        for(auto it = signature.begin(); it!=signature.end(); it++)
            cout<< std::hex << (*it & 0xff);     //16进制输出char自动转int,需要截断字节
        cout << endl << endl;

        ////////////////////////////////////////////////
        // 利用公钥校验与恢复
        RSASS<PSS, SHA1>::Verifier verifier( publicKey );

        StringSource( digest+signature, true,
            new SignatureVerificationFilter(
                verifier, NULL,
                SignatureVerificationFilter::THROW_EXCEPTION
            ) // SignatureVerificationFilter
        ); // StringSource

    } //SignatureVerificationFilter::THROW_EXCEPTION 验证失败抛出异常

    catch( CryptoPP::Exception& e ) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    system("pause");
    return 0;
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

参考

[1]http://www.codegur.me/37488545/how-to-build-crypto-5-6-2-in-msvc2013-for-qt
[2]http://cryptopp.com/wiki/Fips_dll
[3]http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html
[4]http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html
[5]http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html
[6]http://www.office68.com/computer/10174.html


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值