市场导向,技术为本

尘土十分归举子,乾坤大半属偷儿
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

使用Crypto++5.5.2完成RSA加解密

Posted on 2011-09-12 00:22  上海•鹰  阅读(631)  评论(0编辑  收藏  举报

原文在这里:

http://hi.baidu.com/magic475/blog/item/e8b82139020ae622b8998f96.html

 

忙活了一周,基本完成了Crypto++库中关于RSA加解密的API封装!这一周里,查了很多Crypto++的相关资料,感觉这方面的内容乏善可陈, 或者太简单,或者太笼统!本文希望能给使用Crypto++的朋友带来一些帮助,主要还是源代码了,实在没有时间码文字!在测试过程中,感觉 Crypto++还是非常高效的,期待更多的人使用Crypto++。此外,Crypto++的源代码极富研究价值,是深入学习C++的经典材料!爱好 C++的你,千万别错过了~

本文提供的C++源代码已在Redhat Enterprise Server 5.0和Windows XP平台编译链接成功,使用的编译器分别是g++ 3.4.6、Visual C++ 6.0 (SP 6)。由于两个平台的代码差别不大,仅提供Linux平台的代码!如果你需要Windows平台的代码,可以向我索取,留下你的邮件地址即可!如果你在使 用过程中,遇到任何问题,也欢迎你给我留言!

源程序主要包括五个文件:MyRSA.h、 MyRSA.cpp、Main.h、Main.cpp、makefile;两个目录:lib目录包含libcryptopp.a,include目录包含 Crypto++5.5.2中的所有.h头文件。对了,上述五个文件与lib,include目录在同一层目录!需要说明的是,makefile是借用了 一个兄弟的,忘记名字了,不好意思:-)

哈,还是贴代码吧!

/************************** 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));
    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;
}

/************************** Makefile ********************************/
# The executable file name.
PROGRAM := myrsa

# The directories in which source files reside.
SRCDIRS := . # current directory

# The source file types (headers excluded).
SRCEXTS := .cpp

# The flags used by the cpp (man cpp for more).
CPPFLAGS :=

# The compiling flags used only for C.
# If it is a C++ program, no need to set these flags.
# If it is a C and C++ merging program, set these flags for the C parts.

CFLAGS :=

CFLAGS +=

# The compiling flags used only for C++.
# If it is a C program, no need to set these flags.
# If it is a C and C++ merging program, set these flags for the C++ parts.

CXXFLAGS := -g -O2 -I./include

CXXFLAGS +=

# The library and the link options ( C and C++ common).

LDFLAGS := -L./lib -lcryptopp

LDFLAGS +=


## Implict Section: change the following only when necessary.

##=============================================================================

# The C program compiler. Uncomment it to specify yours explicitly.

#CC = gcc

# The C++ program compiler. Uncomment it to specify yours explicitly.

CXX = g++

# Uncomment the 2 lines to compile C programs as C++ ones.

CC = $(CXX)

CFLAGS = $(CXXFLAGS)

# The command used to delete file.

RM = rm -f


## Stable Section: usually no need to be changed. But you can add more.

##=============================================================================

SHELL = /bin/sh

SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))

OBJS = $(foreach x,$(SRCEXTS), \
      $(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES))))

DEPS = $(patsubst %.o,%.d,$(OBJS))



.PHONY : all objs clean cleanall rebuild

all : $(PROGRAM)



# Rules for creating the dependency files (.d).

#---------------------------------------------------

%.d : %.c

    @$(CC) -MM -MD $(CFLAGS) $<

%.d : %.C

    @$(CC) -MM -MD $(CXXFLAGS) $<

%.d : %.cc

    @$(CC) -MM -MD $(CXXFLAGS) $<

%.d : %.cpp

    @$(CC) -MM -MD $(CXXFLAGS) $<

%.d : %.CPP

    @$(CC) -MM -MD $(CXXFLAGS) $<

%.d : %.c++

    @$(CC) -MM -MD $(CXXFLAGS) $<

%.d : %.cp

    @$(CC) -MM -MD $(CXXFLAGS) $<

%.d : %.cxx

    @$(CC) -MM -MD $(CXXFLAGS) $<

# Rules for producing the objects.

#---------------------------------------------------

objs : $(OBJS)

%.o : %.c

    $(CC) -c $(CPPFLAGS) $(CFLAGS) $<

%.o : %.C

    $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<

%.o : %.cc

    $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<

%.o : %.cpp

    $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<

%.o : %.CPP

    $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<

%.o : %.c++

    $(CXX -c $(CPPFLAGS) $(CXXFLAGS) $<

%.o : %.cp

    $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<

%.o : %.cxx

    $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<

# Rules for producing the executable.

#----------------------------------------------

$(PROGRAM) : $(OBJS)

ifeq ($(strip $(SRCEXTS)), .c) # C file

    $(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)

else                            # C++ file

    $(CXX) -o $(PROGRAM) $(OBJS) $(LDFLAGS)

endif

-include $(DEPS)

rebuild: clean all

clean :
    @$(RM) *.o *.d
cleanall: clean
    @$(RM) $(PROGRAM) $(PROGRAM).exe