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;
}

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

时间: 2024-12-19 22:45:42

crypto++RSA数字签名的相关文章

go语言 RSA数字签名和验证签名

package main import ( "crypto" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/pem" "errors" "fmt" "io/ioutil" ) func main() { str := "from

JDK自带方法实现RSA数字签名

JDK只支持MD2withRSA, MD5withRSA, SHA1withRSA 其他的如SHA512withRSA需要第三方包支持,如BC(bouncy castle) JDK的密钥长度默认仍是1024 1 package jdbc.pro.lin; 2 3 import java.security.InvalidKeyException; 4 import java.security.NoSuchAlgorithmException; 5 import java.security.Priv

JAVA RSA 数字签名

import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; public class GenerateKeyPair { private String priKey; private String pubKey; public void run() { try { java.security.Key

Crypto++ RSA从字符串读取公私匙

string and StringSource (load): string spki = ...; StringSource ss(spki, true /*pumpAll*/); RSA::PublicKey publicKey; publicKey.Load(ss); vector and ArraySource (load): vector<byte> spki = ...; ArraySource as(&spki[0], spki.length(), true /*pump

RSA加密异常

在利用RSA进行数据加密时,出现如下异常: Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes at com.sun.crypto.provider.RSACipher.a(DashoA13*..) at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..) a

【C#公共帮助类】给大家分享一些加密算法 (DES、HashCode、RSA、AES等)

AES 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用.AES先进加密算法是一向被认为牢不可破的加密算法,针对这项加密算法的攻击是异常复杂的,事实上想要完全破解AES花费的时间要以数十亿年计,极大的保证了数据的安全性. 这里有两个加密.解密方法: 一种是带密钥的加密:一种是动态加密,就是不需要密钥,密钥被动态生成

RSA算法加密解密

该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1. jar 注意:RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行. RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常: Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes a

java RSA加密生成license,用CPU序列号生成机器码

? license里就是一些注册信息,键值对组成的字符串 ? 对称加密: DES,AES,加密解密都用一个秘钥,速度快 非对称机密 RSA,可以私钥加密公钥解密,也可以公钥机密私钥解密,速度慢 注意:RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行.RSA加密对明文的长度是有限制的,如果加密数据过大会抛出异常: ? 常见加密算法 DES? ??? DES是Data Encryption Standard(数据加密标准)的缩写,DES算法为密

java RSA加密解密

该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1. jar 注意: RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行. RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常: Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes