RSA演算法加解密---crypto++庫和OpenSSL庫
1. OpenSSL庫
a、 方式一:
#include<string.h>
#include <openssl/rsa.h>#pragma comment(lib,"libeay32.lib")#pragma comment(lib,"ssleay32.lib")
typedef unsigned char BYTE;
int main(int argc, char* argv[])
{
BIGNUM b={0};
RSA* pRsa = RSA_generate_key( 1024 ,RSA_F4,0,0);
//pRsa中包含了N D,你這裡自己修改就可以了char sz[]
int len = RSA_size( pRsa );
BYTE* p =new BYTE[ len ];
memset(p,0,len);
RSA_public_encrypt( sizeof(sz) , (unsigned char*)sz , p , pRsa , RSA_PKCS1_PADDING );
charout[1024]={0};
RSA_private_decrypt( len , p , (unsigned char*)out , pRsa , RSA_PKCS1_PADDING );
printf("%s/n"
RSA_free( pRsa );
return0;
}
b、 方式二:使用的RSA演算法中的n、e、d
加密:
/* gcc -o rsa-encrypt rsa-encrypt.c -lcrypto */ #include <openssl/rsa.h> #include <openssl/err.h> #define MODULUS "C8FBCF21" #define PUBLIC_EXPONENT RSA_F4 #define PRIVATE_EXPONENT "97B55D7D" int main() { int ret, flen; BIGNUM * unsigned char *in = "abc"; unsigned char *out; bnn = BN_new(); bne = BN_new(); bnd = BN_new(); BN_hex2bn(&bnn, MODULUS); BN_set_word(bne, PUBLIC_EXPONENT); BN_hex2bn(&bnd, PRIVATE_EXPONENT); RSA *r = RSA_new(); r->n = bnn; r->e = bne; r->d = bnd; RSA_print_fp(stdout, r, 5); flen = RSA_size(r);// - 11; out = (char *)malloc(flen); bzero(out, flen); //memset(out, 0, flen); printf("Begin encrypt.../n"); ret = RSA_public_encrypt(flen, in, out, r, RSA_NO_PADDING); if (ret < 0) { printf("Encrypt failed!/n"); return 1; } printf("Size:%d/n", ret); printf("ClearText:%s/n", in); printf("CipherText(Hex):/n"); int i; for (i=0; i<ret; i++) { printf("0x%02x, ", *out); out++; } printf("/n"); //free(out); RSA_free(r); return 0; } |
解密:
/* gcc -o rsa-decrypt rsa-decrypt.c -lcrypto */ #include <openssl/rsa.h> #define MODULUS "C8FBCF21" #define PUBLIC_EXPONENT RSA_F4 #define PRIVATE_EXPONENT "97B55D7D" int main() { int ret, flen; BIGNUM *bnn, *bne, *bnd; unsigned char in[] = {0x51, 0xc2, 0x8d, 0xc6}; unsigned char *out; bnn = BN_new(); bne = BN_new(); bnd = BN_new(); BN_hex2bn(&bnn, MODULUS); BN_set_word(bne, PUBLIC_EXPONENT); BN_hex2bn(&bnd, PRIVATE_EXPONENT); RSA *r = RSA_new(); r->n = bnn; r->e = bne; r->d = bnd; RSA_print_fp(stdout, r, 5); flen = RSA_size(r); out = (unsigned char *)malloc(flen); bzero(out, flen); printf("Begin decrypt.../n"); ret = RSA_private_decrypt(sizeof(in), in, out, r, RSA_NO_PADDING); if (ret < 0) { printf("Decrypt failed!/n"); return 1; } printf("Size:%d/n", ret); printf("ClearText:%s/n", out); free(out); RSA_free(r); return 0; } |
2. crypto++庫
a、 方式一:
閒來無事研究了一下RSA演算法,發現crypto++這個開源加密庫很不錯(這裡就不介紹了,有興趣可以上網上找到這方面的資料),不過用起來確實麻煩,特別是RSA演算法,USER GUIDE裡的例子程式只支援公鑰與私鑰都是檔案的方式,不支援支接用N,D,E初始化的方式。廢話不說,看程式:
//標頭檔案"RsaInterface.h"
#pragma once
//#include "stdafx.h"
#include "rsa.h"
#include "hex.h"
#include "files.h"
#include "rng.h"
#include "default.h"
#include "randpool.h"
#include "ida.h"
#include "base64.h"
#include "des.h"
#include "modes.h"
#include "socketft.h"
#include "wait.h"
#include "factory.h"
#include "whrlpool.h"
#include "validate.h"
#include "osrng.h"
#include <iostream>
USING_NAMESPACE(CryptoPP)
USING_NAMESPACE(std)
#pragma comment(lib, "cryptlib.lib") // crypto++的庫,要在工程中設定其目錄,具體做法可以參照網上的介紹資料
class RSAInterface
{
public:
RSA::PrivateKey m_privateKey;
RSA::PublicKey m_publicKey;
Integer n;
Integer e;
Integer d;
public:
RSAInterface(void);
~RSAInterface(void);
//n,d,e必須是10進位制數,當用RSA-TOOL生成N,D,E時Number Base要選10
RSA::PrivateKey GenerateRSAPrivateKey(const Integer &n, const Integer &d,const Integer &e);
RSA::PublicKey GenerateRSAPublicKey(const Integer &n, const Integer &e);//n,d,e必須是10進位制數
string RSAEncryptString(string plain);
string RSADecryptString(string cipher);
bool RSASet_n(Integer &nn);
bool RSASet_e(Integer &ee);
bool RSASet_d(Integer &dd);
};
//實現檔案"RsaInterface.cpp"
#include "stdafx.h"
#include "RsaInterface.h"
RSAInterface::RSAInterface(void)
: n("") //可以在這裡直接填入N,D,E值,這樣就不用在加密前初始化公鑰與私鑰了。
, d("")
, e("")
{
// 初始化公鑰和私鑰
m_privateKey=GenerateRSAPrivateKey(n, d, e);
m_publicKey=GenerateRSAPublicKey(n, e);
}
RSAInterface::~RSAInterface(void)
{
}
RSA::PrivateKey RSAInterface::GenerateRSAPrivateKey(const Integer &n, const Integer &d, const Integer &e)
{
InvertibleRSAFunction params;
params.Initialize(n,e,d);
RSA::PrivateKey m_privateKey( params );
return m_privateKey;
}
RSA::PublicKey RSAInterface::GenerateRSAPublicKey(const Integer &n, const Integer &e)
{
RSAFunction params;
params.Initialize(n,e);
RSA::PublicKey m_publicKey( params );
return m_publicKey;
}
string RSAInterface::RSAEncryptString(string plain)
{
AutoSeededRandomPool rng;
// Encryption
string cipher;
RSAES_OAEP_SHA_Encryptor en( m_publicKey );
StringSource( plain, true,
new PK_EncryptorFilter( rng, en,
new HexEncoder(new StringSink(cipher ))
) // PK_EncryptorFilter
); // StringSource
return cipher;
}
string RSAInterface::RSADecryptString(string cipher)
{
AutoSeededRandomPool rng;
// Decryption
string plain;
RSAES_OAEP_SHA_Decryptor de( m_privateKey );
StringSource( cipher, true,
new HexDecoder(new PK_DecryptorFilter( rng, de,
new StringSink( plain ))
) // PK_DecryptorFilter
); // StringSource
return plain;
}
bool RSAInterface::RSASet_n(Integer &nn)
{
n=nn;
return TRUE;
}
bool RSAInterface::RSASet_e(Integer &ee)
{
e=ee;
return TRUE;
}
bool RSAInterface::RSASet_d(Integer &dd)
{
d=dd;
return TRUE;
}
// 用法:
RSAInterface myRSA;
//n,d,e可以用RSATOOLS這個工具生成,不過要注意生成時選基數為10,因為這個庫裡的N,D,E是10進位制的
//如果嫌下面的這個KEY的初始化還麻煩也可以直接在RSAInterface 類的初始化中直接填入N,D,E值,以下兩行就可以不呼叫
myRSA.GenerateRSAPrivateKey(const Integer &n, const Integer &d,const Integer &e);//實際使用時填入實際的N,D,E值
myRSA.GenerateRSAPublicKey(const Integer &n, const Integer &e);//n,d,e必須是10進位制數
//加密字串
string myRSA.RSAEncryptString(string plain);
//解密字串
string myRSA.RSADecryptString(string cipher);
b、 方式二:
/************************** MyRSA.h ********************************/
#ifndef __MYRSA_H__
#define __MYRSA_H__
#include <string>
#include "files.h"
#include "filters.h"
#include "hex.h"
#include "randpool.h"
#include "rsa.h"
using namespace std;
using namespace CryptoPP;
class CMyRSA
{
public:
CMyRSA(void);
virtual ~CMyRSA(void);
//You must set the KeyLength 512, 1024, 2048 ...
void GenerateKey(const unsigned int KeyLength, const char *Seed, RSAES_OAEP_SHA_Decryptor &Priv, RSAES_OAEP_SHA_Encryptor &Pub);
void GenerateKey(const unsigned int KeyLength, const char *Seed, string &strPriv, string &strPub);
//use public key to encrypt
void EncryptString(const RSAES_OAEP_SHA_Encryptor &Pub, const char *Seed, const string &Plaintext, string &Ciphertext);
void EncryptString(const string &strPub, const char *Seed, const string &Plaintext, string &Ciphertext);
//use private key to decrypt
void DecryptString(const RSAES_OAEP_SHA_Decryptor &Priv, const string &Ciphertext, string &Plaintext);
void DecryptString(const string &strPriv, const string &Ciphertext, string &Plaintext);
private:
static RandomPool & RNG(void);
private:
static RandomPool m_sRandPool;
};
#endif /* End of __MYRSA_H__ */
/************************** MyRSA.cpp ********************************/
#include "MyRSA.h"
CMyRSA::CMyRSA()
{
}
CMyRSA::~CMyRSA(void)
{
}
void CMyRSA::GenerateKey(const unsigned int KeyLength, const char *Seed, RSAES_OAEP_SHA_Decryptor &Priv, RSAES_OAEP_SHA_Encryptor &Pub)
{
RandomPool RandPool;
RandPool.IncorporateEntropy((byte *)Seed, strlen(Seed));
//generate private key
Priv = RSAES_OAEP_SHA_Decryptor(RandPool, KeyLength);
//generate public key using private key
Pub = RSAES_OAEP_SHA_Encryptor(Priv);
}
void CMyRSA::GenerateKey(const unsigned int KeyLength, const char *Seed, string &strPriv, string &strPub)
{
RandomPool RandPool;
RandPool.IncorporateEntropy((byte *)Seed, strlen(Seed));
//generate private key
RSAES_OAEP_SHA_Decryptor Priv(RandPool, KeyLength);
HexEncoder PrivateEncoder(new StringSink(strPriv));//本部落格作者加:就為了這句程式碼整整找了1天!
Priv.DEREncode(PrivateEncoder);
PrivateEncoder.MessageEnd();
//generate public key using private key
RSAES_OAEP_SHA_Encryptor Pub(Priv);
HexEncoder PublicEncoder(new StringSink(strPub));
Pub.DEREncode(PublicEncoder);
PublicEncoder.MessageEnd();
}
void CMyRSA::EncryptString(const RSAES_OAEP_SHA_Encryptor &Pub, const char *Seed, const string &Plaintext, string &Ciphertext)
{
RandomPool RandPool;
RandPool.IncorporateEntropy((byte *)Seed, strlen(Seed));
int MaxMsgLength = Pub.FixedMaxPlaintextLength();
for (int i = Plaintext.size(), j=0; i > 0; i -= MaxMsgLength, j += MaxMsgLength)
{
string PartPlaintext = Plaintext.substr(j, MaxMsgLength);
string PartCiphertext;
StringSource(PartPlaintext, true, new PK_EncryptorFilter(RandPool, Pub, new HexEncoder(new StringSink(PartCiphertext))));
Ciphertext += PartCiphertext;
}
}
void CMyRSA::EncryptString(const string &strPub, const char *Seed, const string &Plaintext, string &Ciphertext)
{
StringSource PublicKey(strPub, true, new HexDecoder);
RSAES_OAEP_SHA_Encryptor Pub(PublicKey);
RandomPool RandPool;
RandPool.IncorporateEntropy((byte *)Seed, strlen(Seed));
int MaxMsgLength = Pub.FixedMaxPlaintextLength();
for (int i = Plaintext.size(), j=0; i > 0; i -= MaxMsgLength, j += MaxMsgLength)
{
string PartPlaintext = Plaintext.substr(j, MaxMsgLength);
string PartCiphertext;
StringSource(PartPlaintext, true, new PK_EncryptorFilter(RandPool, Pub, new HexEncoder(new StringSink(PartCiphertext))));
Ciphertext += PartCiphertext;
}
}
void CMyRSA::DecryptString(const RSAES_OAEP_SHA_Decryptor &Priv, const string &Ciphertext, string &Plaintext)
{
//indicate the ciphertext in hexcode
int CiphertextLength = Priv.FixedCiphertextLength() * 2;
for (int i = Ciphertext.size(), j=0; i > 0; i -= CiphertextLength, j += CiphertextLength)
{
string PartCiphertext = Ciphertext.substr(j, CiphertextLength);
string PartPlaintext;
StringSource(PartCiphertext, true, new HexDecoder(new PK_DecryptorFilter(RNG(), Priv, new StringSink(PartPlaintext))));
Plaintext += PartPlaintext;
}
}
void CMyRSA::DecryptString(const string &strPriv, const string &Ciphertext, string &Plaintext)
{
StringSource PrivKey(strPriv, true, new HexDecoder);
RSAES_OAEP_SHA_Decryptor Priv(PrivKey);
//indicate the ciphertext in hexcode
int CiphertextLength = Priv.FixedCiphertextLength() * 2;
for (int i = Ciphertext.size(), j=0; i > 0; i -= CiphertextLength, j += CiphertextLength)
{
string PartCiphertext = Ciphertext.substr(j, CiphertextLength);
string PartPlaintext;
StringSource(PartCiphertext, true, new HexDecoder(new PK_DecryptorFilter(RNG(), Priv, new StringSink(PartPlaintext))));
Plaintext += PartPlaintext;
}
}
RandomPool & CMyRSA::RNG(void)
{
return m_sRandPool;
}
RandomPool CMyRSA::m_sRandPool;
/************************** Main.h ********************************/
#ifndef __MAIN_H__
#define __MAIN_H__
#endif /* End of __MAIN_H__ */
/************************** Main.cpp ********************************/
#include <unistd.h>
#include <iostream>
#include "Main.h"
#include "MyRSA.h"
/***** STATIC VARIABLES *****/
static RSAES_OAEP_SHA_Encryptor g_Pub;
static RSAES_OAEP_SHA_Decryptor g_Priv;
static string g_strPub;
static string g_strPriv;
int main(int argc, char *argv[])
{
try
{
char Seed[1024], Message[1024], MessageSeed[1024];
unsigned int KeyLength;
CMyRSA MyRSA;
cout << "Key length in bits: ";
cin >> KeyLength;
cout << "/nRandom Seed: ";
ws(cin);
cin.getline(Seed, 1024);
cout << "/nMessage: ";
ws(cin);
cin.getline(Message, 1024);
cout << "/nRandom Message Seed: ";
ws(cin);
cin.getline(MessageSeed, 1024);
MyRSA.GenerateKey(KeyLength, Seed, g_Priv, g_Pub);
//MyRSA.GenerateKey(KeyLength, Seed, g_strPriv, g_strPub);
//If generate key in RSAES_OAEP_SHA_Encryptor and RSAES_OAEP_SHA_Decryptor, please note four lines below
/*
cout << "g_strPub = " << g_strPub << endl;
cout << endl;
cout << "g_strPriv = " << g_strPriv << endl;
cout << endl;
*/
string Plaintext(Message);
string Ciphertext;
MyRSA.EncryptString(g_Pub, MessageSeed, Plaintext, Ciphertext);
//MyRSA.EncryptString(g_strPub, MessageSeed, Plaintext, Ciphertext);
cout << "/nCiphertext: " << Ciphertext << endl;
cout << endl;
string Decrypted;
MyRSA.DecryptString(g_Priv, Ciphertext, Decrypted);
//MyRSA.DecryptString(g_strPriv, Ciphertext, Decrypted);
cout << "/nDecrypted: " << Decrypted << endl;
return 0;
}
catch(CryptoPP::Exception const &e)
{
cout << "/nCryptoPP::Exception caught: " << e.what() << endl;
return -1;
}
catch(std::exception const &e)
{
cout << "/nstd::exception caught: " << e.what() << endl;
return -2;
}
return -3;
}