crypto++RSA数字签名

Posted ll7

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了crypto++RSA数字签名相关的知识,希望对你有一定的参考价值。

      “发送报文时,发送方用一个哈希函数从报文文本中生成报文摘要,然后用自己的私人密钥对这个摘要进行加密,这个加密后的摘要将作为报文的数字签名和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再用发送方的公用密钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认该数字签名是发送方的。  

      以上内容来自百度百科,数字签名过程。

      本来想着用rsa加解密和MD5就可以实现数字签名。查询了网上的文章,经过自己尝试。发现只能用公钥加密,私钥解密。这和数字签名刚好是相反的,在CSDN里发现也有人问过这个问题。这是加密函数RSAES_OAEP_SHA_Encryptor e(publicKey);这是解密函数RSAES_OAEP_SHA_Decryptor d(privateKey);

      上面是用公钥加密,私钥解密的。和数字签名好像是反过来的。到网上搜了搜,好像解决不了。我就自己去看了一下Crypto++rsa的wiki。本人的英语水平不行、用有道一边猜一边翻译,明白了个大概吧。地址给大家https://www.cryptopp.com/wiki/RSA_Signature_Schemes#Downloads。可以看一看,我也没看明白多少就不给大家说那么多了。方法教给大家,自己去看吧。

      我把内容拷进来吧,不想戳进去的也可以在这里看。

 

Sample Programs

The following is a handful of sample programs demonstrating ways to create keys, sign messages and verify messages.

Generate Keys

///////////////////////////////////////
// Pseudo Random Number Generator伪随机数发生器
AutoSeededRandomPool rng;

///////////////////////////////////////
// Generate Parameters  密钥生成所需参数
InvertibleRSAFunction params;
params.GenerateRandomWithKeySize(rng, 1536);

///////////////////////////////////////
// Generated Parameters   
Integer n = params.GetModulus();
Integer p = params.GetPrime1();
Integer q = params.GetPrime2();
Integer d = params.GetPrivateExponent();
Integer e = params.GetPublicExponent();

///////////////////////////////////////
// Dump
cout << "RSA Parameters:" << endl;
cout << " n: " << n << endl;
cout << " p: " << p << endl;
cout << " q: " << q << endl;
cout << " d: " << d << endl;
cout << " e: " << e << endl;
cout << endl;

///////////////////////////////////////
// Create Keys
RSA::PrivateKey privateKey(params);
RSA::PublicKey publicKey(params);

RSA Signature Scheme with Appendix  

//带有附录的RSA签名方案

AutoSeededRandomPool rng;

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

RSA::PrivateKey privateKey(parameters);
RSA::PublicKey publicKey(parameters);

// Message
string message = "Yoda said, Do or Do Not. There is no try.";

// Signer object
RSASS<PSS, SHA1>::Signer signer(privateKey);

// Create signature space
size_t length = signer.MaxSignatureLength();
SecByteBlock signature(length);

// Sign message
length = signer.SignMessage(rng, (const byte*) message.c_str(),
    message.length(), signature);

// Resize now we know the true size of the signature
signature.resize(length); // Verifier object RSASS<PSS, SHA1>::Verifier verifier(publicKey); // Verify bool result = verifier.VerifyMessage((const byte*)message.c_str(), message.length(), signature, signature.size()); // Result if(true == result) { cout << "Signature on message verified" << endl; } else { cout << "Message verification failed" << endl; }

RSA Signature Scheme with Appendix (Filters)

RSA签名方案与附录(过滤器)

// Generate ot Load keys
RSA::PrivateKey privateKey = ...;
RSA::PublicKey publicKey = ...;

// Message
string message = "Yoda said, Do or Do Not. There is no try.";
string signature, recovered;

////////////////////////////////////////////////
// Sign and Encode
RSASS<PSS, SHA1>::Signer signer(privateKey);

StringSource ss1(message, true, 
    new SignerFilter(rng, signer,
        new StringSink(signature)
  ) // SignerFilter
); // StringSource

////////////////////////////////////////////////
// Verify and Recover
RSASS<PSS, SHA1>::Verifier verifier(publicKey);

StringSource ss2(message+signature, true,
    new SignatureVerificationFilter(
        verifier,
        new StringSink(recovered),
        SignatureVerificationFilter::THROW_EXCEPTION |
        SignatureVerificationFilter::PUT_MESSAGE
  ) // SignatureVerificationFilter
); // StringSource

////////////////////////////////////////////////
// No exception - use recovered message
...

RSA Probabilistic Signature Scheme with Recovery

带恢复的RSA概率签名方案

////////////////////////////////////////////////
// Generate keys
AutoSeededRandomPool rng;

InvertibleRSAFunction params;
params.GenerateRandomWithKeySize(rng, 1536);

RSA::PrivateKey privateKey(params);
RSA::PublicKey publicKey(params);

// Signing      
RSASS<PSSR, SHA1>::Signer signer(privateKey);
RSASS<PSSR, SHA1>::Verifier verifier(publicKey);

// Setup
byte message[] = "RSA-PSSR Test";
size_t messageLen = sizeof(message);      

////////////////////////////////////////////////
// Sign and Encode
SecByteBlock signature(signer.MaxSignatureLength(messageLen));

size_t signatureLen = signer.SignMessageWithRecovery(rng, message,
    messageLen, NULL, 0, signature);

// Resize now we know the true size of the signature
signature.resize(signatureLen);

////////////////////////////////////////////////
// Verify and Recover
SecByteBlock recovered(
    verifier.MaxRecoverableLengthFromSignatureLength(signatureLen)
);

DecodingResult result = verifier.RecoverMessage(recovered, NULL,
    0, signature, signatureLen);

if (!result.isValidCoding) {
    throw Exception(Exception::OTHER_ERROR, "Invalid Signature");
}

////////////////////////////////////////////////
// Use recovered message
//  MaxSignatureLength is likely larger than messageLength
recovered.resize(result.messageLength);
...

RSA Probabilistic Signature Scheme with Recovery (Filter)

RSA概率签名方案与恢复(过滤)

////////////////////////////////////////////////
// Generate or Load keys
RSA::PrivateKey privateKey = ...;
RSA::PublicKey publicKey = ...; 

////////////////////////////////////////////////
// Setup
string message = "RSA-PSSR Test", signature, recovered;    

////////////////////////////////////////////////
// Sign and Encode
RSASS<PSSR, SHA1>::Signer signer(privateKey);

StringSource ss1(message, true, 
    new SignerFilter(rng, signer,
        new StringSink(signature),
        true // putMessage for recovery
   ) // SignerFilter
); // StringSource

////////////////////////////////////////////////
// Verify and Recover
RSASS<PSSR, SHA1>::Verifier verifier(publicKey);

StringSource ss2(signature, true,
    new SignatureVerificationFilter(
        verifier,
        new StringSink(recovered),
        THROW_EXCEPTION | PUT_MESSAGE
   ) // SignatureVerificationFilter
); // StringSource

cout << "Verified signature on message" << endl;

RSA Signature Scheme (PKCS v1.5)

RSA签名方案(PKCS v1.5)

Though similar to RSA-SSA, RSASSA_PKCS1v15_SHA_Signer and RSASSA_PKCS1v15_SHA_Verifier uses PKCS v1.5 padding. The MD2 and MD5 variants of RSASSA_PKCS1v15_<Digest>_Signer and RSASSA_PKCS1v15_<Digest>_Verifier should not be used.

虽然类似于RSA-SSA,RSASSA_PKCS1v15_SHA_Signer和RSASSA_PKCS1v15_SHA_Verifier使用PKCS v1.5填充。  MD2和MD5的变种RSASSA_PKCS1v15_ <Verifier > _Signer和RSASSA_PKCS1v15_ <Verifier > _Verifier不应使用。

AutoSeededRandomPool rng;

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

RSA::PrivateKey privateKey(parameters);
RSA::PublicKey publicKey(parameters);

// Message
string message = "Yoda said, Do or Do Not. There is no try.";

// Signer object
RSASSA_PKCS1v15_SHA_Signer signer(privateKey);

// Create signature space
size_t length = signer.MaxSignatureLength();
SecByteBlock signature(length);

// Sign message
length = signer.SignMessage(rng, (const byte*) message.c_str(),
    message.length(), signature);

// Resize now we know the true size of the signature
signature.resize(length);

// Verifier object
RSASSA_PKCS1v15_SHA_Verifier verifier(publicKey);

// Verify
bool result = verifier.VerifyMessage((const byte*)message.c_str(),
    message.length(), signature, signature.size());

// Result
if(true == result) {
    cout << "Signature on message verified" << endl;
} else {
    cout << "Message verification failed" << endl;
}

RSA Signature Generation Given d and n

给定d和n的RSA签名生成

Given Integers d and n rather than a RSA::PrivateKey, perform the following to create a signer object [1]. Attempting to use a RSA::PrivateKey by calling Initialize (i.e., not factoring n) will result in an exception [2].

给定的整数d和n,而不是一个RSA::PrivateKey,执行以下签名者创建一个对象[1]。试图使用RSA:PrivateKey通过调用初始化(i.e.,而不是考虑n)将导致异常[2]。

// Use InvertibleRSAFunction to factor ‘n‘
InvertibleRSAFunction params;
params.Initialize(n, e, d);

RSA::PrivateKey(params);

...

If the public exponent has been misplaced, common values for the exponent are 3 (Microsoft CAPI/C#), 17 (Crypto++), and 65535 (Java).

RSA Signature Verification Given e and n

给定e和n,RSA签名验证,

Given Integers e and n rather than a RSA::PublicKey, perform the following to create a verifier object.

RSASS<PSS, SHA>::Verifier verifier(n, e);
RSASS<PSS, SHA>::Verifier verifier;
verifier.AccessKey().Initialize(n, e);


最后附上我的代码:

#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include "md5.h"
#include<iostream>
#include "pssr.h"
#include <hex.h>
#include "rsa.h"
#include "osrng.h"

using namespace CryptoPP;
#pragma comment(lib, "cryptlib.lib")
using namespace std;

bool md5(const string &src, string &digest)
{
 Weak::MD5 md5;
 StringSource(src, true,
  new HashFilter(md5,
  new HexEncoder(new StringSink(digest))
  )
  );
 return true;
}

int main()
{
 
 try
 {
  ////////////////////////////////////////////////
  // Generate keys
  AutoSeededRandomPool rng;

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

  RSA::PrivateKey privateKey(parameters);
  RSA::PublicKey publicKey(parameters);

  // Message
  string message;
  string signature,md5_message;
  cout << "请输入要签名的内容:";
  cin >> message;
  cout << endl;
  md5(message, md5_message);   //将内容哈希

  cout <<"将信息哈希为摘要:"<<endl<<endl<< md5_message << endl << endl;
  ////////////////////////////////////////////////
  // Sign and Encode
  RSASS<PSS, SHA1>::Signer signer(privateKey);

  StringSource(md5_message, true,
   new SignerFilter(rng, signer,
   new StringSink(signature)
   ) // SignerFilter
   ); // StringSource
  cout << signature << endl<<endl<<endl;
  ////////////////////////////////////////////////
  // Verify and Recover
  RSASS<PSS, SHA1>::Verifier verifier(publicKey);

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

  cout << "Verified signature on message" << endl;

 } // try

 catch (CryptoPP::Exception& e) {
  std::cerr << "Error: " << e.what() << std::endl;
 }

 return 0;
}

        以上内容仅供参考,初学者,若有错误请当即指正。

以上是关于crypto++RSA数字签名的主要内容,如果未能解决你的问题,请参考以下文章

crypto++RSA数字签名

使用 rsa 在 c# 中验证来自节点的签名数据

golang数字签名

C# RSA 等效于 C++ Crypto API 的代码

Crypto模块中的签名算法

Go-ecc数字签名详解与代码