主页 > 原创 | 学习笔记 > 基于Crypto++/Cryptopp的rsa密钥生成,rsa加密、解密,rsa签名、验签

基于Crypto++/Cryptopp的rsa密钥生成,rsa加密、解密,rsa签名、验签

在项目中需要增加一个注册的功能,想到了用rsa非对称加密的方法。对比了openssl等第三方库,最后采用了Cryptopp。

1.源文件整理
可以在http://www.cryptopp.com/获取库的源文件,解压后将文件重新归档。头文件放置到include文件夹,cpp放到src目录。同时去除所有的test相关的cpp及非cpp、h文件。拷本cryptopp目录到工程目录下
2.加入工程
在vs2010工程中增加新的filter,命名为Cryptopp,再增加子filter include和src。将include下的h文件导入到include,将src下的cpp导入到src filter。
2014-06-27_171754
3.编译
打开src,选中所有的cpp文件,更改属性,将预编译头改为pch.h。将工程的vc++路径更新,增加include和src。
2014-06-27_171553
2014-06-27_171631
编译工程,如果编译不过修改一下错误。
4.生成rsa公钥、私钥,经过base64编码后保存到文件
需要导入一些头文件:

#include "iterhash.h"
#include "files.h"
#include "rsa.h"
#include "randpool.h"
#include "hex.h"
#include "base64.h"
#include "osrng.h"
void CKeyController::GenerateRSAKey(unsigned int keyLength, CString decFilename, CString encFilename, CString seed)
{
 RandomPool randPool;
  randPool.Put((byte *)seed.GetBuffer(seed.GetLength()), seed.GetLength());

 RSAES_OAEP_SHA_Decryptor decrypt(randPool, keyLength);
  HexEncoder decFile(new Base64Encoder(new FileSink(decFilename.GetBuffer(decFilename.GetLength()))));

  decrypt.DEREncode(decFile);
 decFile.MessageEnd();

 RSAES_OAEP_SHA_Encryptor encrypt(decrypt);
  HexEncoder encFile(new Base64Encoder(new FileSink(encFilename.GetBuffer(encFilename.GetLength()))));
  encrypt.DEREncode(encFile);

 encFile.MessageEnd();

 return;
}
RandomPool & CKeyController::GlobalRNG()
{
 static RandomPool randomPool;
 return randomPool;
}

5.通过生成的公钥文件加密字符串

CString CKeyController::RSAEncryptString( CString encFilename, CString seed, CString message )
{
 string encString;
 FileSource encFile( encFilename.GetBuffer(encFilename.GetLength()), true, new Base64Decoder(new StringSink(encString)) );
 HexDecoder decoder;
 decoder.Put( (byte*)encString.c_str(), encString.size() );
  decoder.MessageEnd();

 RSAES_OAEP_SHA_Encryptor enc;
 enc.AccessKey().Load(decoder);

  RandomPool randPool;
  randPool.Put( (byte *)seed.GetBuffer(seed.GetLength()), seed.GetLength() );

 string result;
  StringSource( c2s(message), true, new PK_EncryptorFilter(randPool, enc, new HexEncoder(new StringSink(result))) );

  return CString(result.c_str());
}

6.通过生成的私钥文件解密字符串

CString CKeyController::RSADecryptString( CString decFilename, CString ciphertext )
{
 string decString;
 FileSource decFile( decFilename.GetBuffer(decFilename.GetLength()), true, new Base64Decoder(new StringSink(decString)) );
 HexDecoder decoder;
 decoder.Put( (byte*)decString.c_str(), decString.size() );
  decoder.MessageEnd();

 RSAES_OAEP_SHA_Decryptor dec;
 dec.AccessKey().Load(decoder);

  string result;
  StringSource( c2s(ciphertext), true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), dec, new StringSink(result))) );

  return CString(result.c_str());
}

7.使用私钥签名

CString CKeyController::SignMessage( const std::string& privateKeyFileName, const std::string& message )
{
  std::string signedMessage = "";
 string encString;
 FileSource privFile( privateKeyFileName.c_str(), true, new Base64Decoder(new StringSink(encString)));
 RSASSA_PKCS1v15_SHA_Signer priv;

  HexDecoder decoder;
 decoder.Put( (byte*)encString.c_str(), encString.size() );
  decoder.MessageEnd();

 priv.AccessKey().Load(decoder);

 AutoSeededRandomPool rng;
 StringSource s1(message, true, new SignerFilter(rng, priv, new HexEncoder(new StringSink(signedMessage))));
 
  return CString(signedMessage.c_str());
}

8.使用公钥验证签名

bool CKeyController::VerifySignature( const std::string& publicKeyFileName, const std::string& message, const std::string& signedMessage )
{
 string decString;
 FileSource pubFile( publicKeyFileName.c_str(), true, new Base64Decoder(new StringSink(decString)) );
  RSASSA_PKCS1v15_SHA_Verifier pub;

 HexDecoder decoder;
 decoder.Put( (byte*)decString.c_str(), decString.size() );
  decoder.MessageEnd();

 pub.AccessKey().Load(decoder);

  StringSource signatureFile( signedMessage, true, new HexDecoder);
 if (signatureFile.MaxRetrievable() != pub.SignatureLength())
  { throw std::string( "Signature Size Problem" ); }

  SecByteBlock signature(pub.SignatureLength());
  signatureFile.Get(signature, signature.size());

 VerifierFilter *verifierFilter = new VerifierFilter(pub);
 verifierFilter->Put(signature, pub.SignatureLength());
  StringSource s(message, true, verifierFilter);

  return verifierFilter->GetLastResult();
}

9.测试函数调用

void CKeyController::testRSA()
{
  CString encryptKey = _T("key.pub");
 CString decryptKey = _T("key.pri");
 CString seed = _T("seed");

  //GenerateRSAKey( 1024, decryptKey, encryptKey, seed );

 CString message = _T("X3BA-9NSF-8N9Q-UWQC-U7FX-AZZF-JAJW");

 CString encryptedText = RSAEncryptString( encryptKey, seed, message );

  CString decryptedText = RSADecryptString( decryptKey, encryptedText );
 
  CString signedMessage = SignMessage("key.pri", c2s(decryptedText));

 bool verified = VerifySignature("key.pub", c2s(message), c2s(signedMessage));
}

10.工具函数如base64转码,字符串转换

std::string CKeyController::EncodeBase64( string message )
{
  string encode;
  StringSource(message, true, new Base64Encoder(new StringSink(encode)));
 return encode;
}

std::string CKeyController::DecodeBase64( string message )
{
  string decode;
  StringSource(message, true, new Base64Decoder(new StringSink(decode)));
 return decode;
}

CString CKeyController::hashString( CString message )
{
 string digest;
  SHA256 hash;
  StringSource foo(c2s(message), true, new HashFilter(hash, new HexEncoder(new StringSink(digest))));
 return CString(digest.c_str());
}

CString CKeyController::hashFile( CString fileName )
{
 string digest;
  SHA256 hash;
  FileSource(fileName, true, new HashFilter(hash, new HexEncoder(new StringSink(digest))));
 return CString(digest.c_str());
}

std::string c2s( CString &cs )
{
 CT2CA pszConvertedAnsiString(cs);
 std::string strStd(pszConvertedAnsiString);
 return strStd;
}

Tags: Crypto++ Cryptopp MFC rsa 加密 签名 解密 非对称加密 验签

评论:4

  1. 小浮云 回复
    2014 年 9 月 1 日 于 下午 6:32

    第1、2、3步这种方式我还是第一次见,没实验成功,想问问博主为什么这样用?通过静态库的方式行不行?

    • tianyu 回复
      2014 年 9 月 1 日 于 下午 10:47
      _________________________________________
      / 通过静态库和动态库肯定都是可以的,这样用大概是当时偷懒,把源码导入后直接就能用 \
      | 就没有再细分,也有可能是当时做静态库错误太多懒得改了,这个当时很快就做好了没做 |
      \ 太多的考虑                                   /
       -----------------------------------------
              \   ^__^
               \  (oo)\_______
                  (__)\       )\/\
                      ||----w |
                      ||     ||
      • 小浮云 回复
        2014 年 9 月 3 日 于 上午 10:11

        你为何要这么萌==||

  2. star 回复
    2017 年 1 月 4 日 于 上午 10:48

    CKeyController是自定义?

发表评论

电子邮件地址不会被公开。 必填项已用*标注