1. 程式人生 > >RSA演算法加解密---crypto++庫和OpenSSL庫

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[]

="abcdefg";
   
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"
,out);
    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 *
bnn, *bne, *bnd;
    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;  
}