利用Crypto++实现RSA加密算法

之前做一个项目用到crypto++加密库,可以从官网下载对应的源码,其中有一个test.c文件,详细的演示了各种加密算法的使用方法,因此,在其基础上,我将aes、rsa、MD5进行了简单的封装,以便于更好的使用

MyRSA.h头文件如下:

/*
 * MyRSA.h
 *
 *  Created on: 2013-3-7
 *      Author: wzb
 */

#ifndef MYRSA_H_
#define MYRSA_H_

#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include <iostream>
#include <string>

#include <cryptopp/rsa.h>
#include <cryptopp/hex.h>
#include <cryptopp/osrng.h>
#include <cryptopp/files.h>
#include <cryptopp/md5.h>

using namespace std;
using namespace CryptoPP;

class MyRSA
{
public:
	MyRSA();
	~MyRSA();

	string MD5(const char * message);
	string MD5File(const char * filename);

	void GenerateRSAKey(unsigned int keyLength, const char *privFilename,
			const char *pubFilename);

	string Encrypt(const char * pubFilename, const char * message);
	string Decrypt(const char * privFilename, const char * cipher);

	void SignFile(const char * privFilename, const char * messageFilename,
			const char * signatureFilename);
	bool VerifyFile(const char *pubFilename, const char * messageFilename,
			const char * signatureFilename);

	SecByteBlock SignString(const char *privFilename, const char * message);
	bool VerifyString(const char * pubFilename, const char * messsage,
			const SecByteBlock &SecByteBlock);
private:
	AutoSeededRandomPool _rng;
};

#endif /* MYRSA_H_ */

MyRSA.cpp 源文件如下:

/*
 * MyRSA.cpp
 *
 *  Created on: 2013-3-7
 *      Author: hust
 */
#include "MyRSA.h"
#include <time.h>
MyRSA::MyRSA()
{

}

MyRSA::~MyRSA()
{

}
/*
 * Description: this function is used to calcuate the string 'message' 's hash value
 * Input:
 * 	message: the init string to be hashed
 * Output:
 * 	return the hash of the parameter
 */
string MyRSA::MD5(const char * message)
{
	string digest;
	Weak::MD5 md5;
	StringSource(message, true,
			new HashFilter(md5, new HexEncoder(new StringSink(digest))));
	return digest;
}
/*
 * Description: to calculate the hash of the file and return the hash value(string)
 * Input:
 * 	filename: the file to be calculated the hash value
 * Output:
 *  return the hash value of the file and its type is string
 */
string MyRSA::MD5File(const char * filename)
{
	string digest;
	Weak::MD5 md5;
	FileSource(filename, true,
			new HashFilter(md5, new HexEncoder(new StringSink(digest))));
	return digest;

}

/*
 * Description: generate the RSA public key and private key in separate file
 * Input:
 *  KeyLength: the length of the key, such as 1024...
 *  privFilename: private key file name you want to store the private key
 *  pubFilename: public key file name you want to store the public key
 * Output:
 * 	nothing
 */
void MyRSA::GenerateRSAKey(unsigned int keyLength, const char *privFilename,
		const char *pubFilename)
{
	RSAES_OAEP_SHA_Decryptor priv(_rng, keyLength);
	HexEncoder privFile(new FileSink(privFilename));
	priv.DEREncode(privFile);
	privFile.MessageEnd();

	RSAES_OAEP_SHA_Encryptor pub(priv);
	HexEncoder pubFile(new FileSink(pubFilename));
	pub.DEREncode(pubFile);
	pubFile.MessageEnd();
}

/*
 * Description: this function is used to encrypt the string 'plainText' with the
 * 				private key, and return the cipher
 * Input:
 * 	pubFilename: the public key
 * 	message: the string to be encrypted
 * OutPut:
 *  return the cipher
 */
string MyRSA::Encrypt(const char * pubFilename, const char * message)
{
	FileSource pubFile(pubFilename, true, new HexDecoder);

	RSAES_OAEP_SHA_Encryptor pub(pubFile);
	string result;
	StringSource(message, true,
			new PK_EncryptorFilter(_rng, pub,
					new HexEncoder(new StringSink(result))));
	return result;
}
/*
 * Description: decrypt the cipher with the private key
 * Input:
 * 	privFilename: the private key file
 * 	ciphertext: the string to be decrypted
 * Output:
 * 	return the decrypted string
 */
string MyRSA::Decrypt(const char * privFilename, const char * ciphertext)
{
	FileSource privFile(privFilename, true, new HexDecoder);

	RSAES_OAEP_SHA_Decryptor priv(privFile);
	string result;
	StringSource(ciphertext, true,
			new HexDecoder(
					new PK_DecryptorFilter(_rng, priv,
							new StringSink(result))));
	return result;
}

/*
 * Description: sign the file with the private key, and generate the signature file
 * Input:
 *  privFilename: the private key file
 *  messageFilename: the file to be signed
 *  signatureFilename: the signature file to be generated
 * Output:
 * 	nothing
 */
void MyRSA::SignFile(const char * privFilename, const char *messageFilename,
		const char * signatureFilename)
{
	FileSource priFile(privFilename, true, new HexDecoder);
	RSASS<PKCS1v15, SHA>::Signer priv(priFile);
	FileSource f(messageFilename, true,
			new SignerFilter(_rng, priv,
					new HexEncoder(new FileSink(signatureFilename))));
}

/*
 * Description: verify the file with the public key, and return the answer
 * Input:
 *  pubFilename: the publicFilename
 *  messageFilename: the init message file, and it should be not changed
 *  signatureFilename: the SignFile function generate, and it's used to verify if the message
 *  					file is the original one
 * Output:
 * 	if the message file match the signature file, return true; else return false
 */
bool MyRSA::VerifyFile(const char * pubFilename, const char * messageFilename,
		const char * signatureFilename)
{
	FileSource pubFile(pubFilename, true, new HexDecoder);
	RSASS<PKCS1v15, SHA>::Verifier pub(pubFile);

	FileSource signatureFile(signatureFilename, true, new HexDecoder);
	if (signatureFile.MaxRetrievable() != pub.SignatureLength())
		return false;
	SecByteBlock signature(pub.SignatureLength());
	signatureFile.Get(signature, signature.size());

	VerifierFilter *verifierFilter = new VerifierFilter(pub);
	verifierFilter->Put(signature, pub.SignatureLength());
	FileSource f(messageFilename, true, verifierFilter);

	return verifierFilter->GetLastResult();
}

/*
 * Description: sign the string with the private key, and generate the signature
 * Input:
 *  privFilename: the private key file
 *  message: the string to be signed
 * Output:
 * 	return the SecByteBlock signature
 */
SecByteBlock MyRSA::SignString(const char * privFilename, const char * message)
{
	// calculate the md5(HASH) of the message
	string digest = MD5(message);
	FileSource priFile(privFilename, true, new HexDecoder);
	RSASSA_PKCS1v15_SHA_Signer priv(priFile);

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

	// sign message
	priv.SignMessage(_rng, (const byte*) digest.c_str(), digest.length(),
			signature);

	return signature;
}
/*
 * Description: verify the file with the public key, and return the answer
 * Input:
 *  pubFilename: the publicFilename
 *  message: the original message, and it should be not changed
 *  signature: the SignString function returned, and it's used to verify if the message
 *  		   is the original one
 * Output:
 * 	if the message match the signature , return true; else return false
 */
bool MyRSA::VerifyString(const char * pubFilename, const char * message,
		const SecByteBlock & signature)
{
	// calculate the md5 of the message first
	string digest = MD5(message);
	FileSource pubFile(pubFilename, true, new HexDecoder);
	RSASSA_PKCS1v15_SHA_Verifier verifier(pubFile);

	bool result = verifier.VerifyMessage((const byte*) digest.c_str(),
			digest.length(), signature, signature.size());
	return result;
}


 int main() {
 char privFilename[128] = "prvKey", pubFilename[128] = "pubKey";
 unsigned int keyLength = 1024;
 clock_t start, finish;
 double duration;


 //	cout << "Key length in bits: ";
 //	cin >> keyLength;

 //	cout << "\nSave private key to file: ";
 //	cin >> privFilename;

 //	cout << "\nSave public key to file: ";
 //	cin >> pubFilename;


 MyRSA rsa;


 start = clock();
 cout << "============encrypt and decrypt================" << endl;
 rsa.GenerateRSAKey(keyLength, privFilename, pubFilename);
 string message = "hello world, i am a student from huazhong university of science and technology!";
 string ciphertext = rsa.Encrypt(pubFilename, message.c_str());
 cout << "The cipher is : " << ciphertext << endl;

 string decrypted = rsa.Decrypt(privFilename, ciphertext.c_str());
 cout << "The recover is : " << decrypted << endl;

 finish = clock();
 duration = (double) (finish - start) / CLOCKS_PER_SEC;
 cout << "The cost is : " << duration << " seconds" << endl;


 cout << "==============sign file================" << endl;
 start = clock();
 string messageFilename = "signTest";
 string signatureFilename = "signature";
 rsa.SignFile(privFilename, messageFilename.c_str(),
 signatureFilename.c_str());

 if (rsa.VerifyFile(pubFilename, messageFilename.c_str(),
 signatureFilename.c_str())) {
 cout << "verify correct!" << endl;
 } else
 cout << "verify error!" << endl;

 finish = clock();
 duration = (double) (finish - start) / CLOCKS_PER_SEC;
 cout << "The sign file cost is : " << duration << " seconds" << endl;


 cout << "============sign string=================" << endl;
 start = clock();
 string plainText = "Sign me, i am a student from huazhong university of science and technology!";

 SecByteBlock signature = rsa.SignString(privFilename, plainText.c_str());
 cout << "The Signature size is : " << signature.size() << endl;

 //cout << endl << "The signature is : " << signature << endl << endl;

 // save the signature to the file
 //ofstream signatureFile("signatureFile");
 //if(signatureFile.is_open() )
 //{
 //	for(int i = 0; i < signature.get
 //}

 if (rsa.VerifyString(pubFilename, plainText.c_str(), signature)) {
 cout << "Verify correct!" << endl;
 } else {
 cout << "Verify wrong!" << endl;
 }

 finish = clock();
 duration = (double) (finish - start) / CLOCKS_PER_SEC;
 cout << "The sign string cost is : " << duration << " seconds" << endl;
 return 0;
 }

在linux系统下,编译命令于上一节差不多

g++ MyRSA.cpp -o rsa -lpthread -lcryptopp

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏不想当开发的产品不是好测试

MD5 in JAVA

using Apache Commons 需要引入org.apache.commons.codec.digest.DigestUtils这个包,pom.xml文...

23110
来自专栏张善友的专栏

在.NET Core 里使用 BouncyCastle 的DES加密算法

.NET Core上面的DES等加密算法要等到1.2 才支持,我们可是急需这个算法的支持,文章《使用 JavaScriptService 在.NET Core ...

3027
来自专栏Java与Android技术栈

Transformer 在RxJava中的使用

Transformer,顾名思义是转换器的意思。早在 RxJava1.x 版本就有了Observable.Transformer、Single.Transfor...

6552
来自专栏GIS讲堂

自己写一个读取Arcgis Server切片的后台服务

Arcgis Server的切片得要有Arcgis Server的支持才能使用,这样就显得比较麻烦,如果对于已经切好的切片怎么样通过自己写的程序来调用展示呢,本...

2133
来自专栏ACM小冰成长之路

DES算法-C/C++实现

闲来无事,车一下轮子,折腾了大半天才搞懂 DESDES 是干毛子的,看了好多博客才弄清楚这个算法的具体原理,真是心累。 只是简单的实现,功能比较简陋,因为参考的...

46410
来自专栏酷玩时刻

微信支付之企业付款

付款之前需要充值: 在调用API接口付款或通过微信支付商户平台网页功能操作付款之前需要登录微信支付商户平台,通过网页充值功能充值(商户平台-交易中心)

1394
来自专栏码匠的流水账

聊聊hystrix的timeout处理

hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/AbstractCommand.java

1612
来自专栏数据结构与算法

HDU 4786Fibonacci Tree(最小生成树)

Problem Description   Coach Pang is interested in Fibonacci numbers while Un...

3676
来自专栏码匠的流水账

聊聊spring cloud gateway的NettyConfiguration

本文主要研究下spring cloud gateway的NettyConfiguration

3011
来自专栏一个会写诗的程序员的博客

【Kotlin 反应式编程】第1讲 你好,Reactive Programming

【Kotlin 反应式编程】第1讲 你好,Reactive Programming

852

扫码关注云+社区