美文网首页
c++下RSA和BLOWFISH加解密-使用Crypto库

c++下RSA和BLOWFISH加解密-使用Crypto库

作者: 大呀大帝国 | 来源:发表于2017-03-03 14:37 被阅读220次

    工作需要使用RSA和BLOWFISH加密,主要使用CRYPTO库,但是CRYPTO并不是很方便使用,封装的有点复杂。我整理CRYPTO的文档,简单的封装了主要的加密和解密方法。代码如下:

    代码需要配置boost和crypto才能运行。

    首先是 data_package_t.hpp 这个类和加解密没有关系,只是简单的封装了shared_array, 添加了一个_size_datalen,能够直接获取数组的长度。方法也很简单,只有一个构造函数和 reset_data。构造函数只有一个参数,传入数组的长度。reset_data 的作用是把数据的数据全部清0.

    
    #ifndef UNIT_TEST_DATA_PACKAGE_T_H
    #define UNIT_TEST_DATA_PACKAGE_T_H
    
    #include <iostream>
    #include <cstring>
    #include <boost/shared_array.hpp>
    
    namespace my_utils {
        namespace types {
            template<typename data_type>
            class package {
            public:
                inline package(std::size_t _init_datalen = 0)
                        : _arr_data(new data_type[_init_datalen]), _size_datalen(_init_datalen) {
                    reset_data();
                }
    
                inline void reset_data() {
                    memset(_arr_data.get(), 0x0, sizeof(data_type) * _size_datalen);
                }
    
                boost::shared_array <data_type> _arr_data;
                std::size_t _size_datalen;
            };
    
            typedef unsigned char data_t;
            typedef package<data_t> data_package_t;
        }
    }
    
    #endif //UNIT_TEST_DATA_PACKAGE_T_H
    

    接下来是主要的头文件 encryption_utils.h 里面定义了主要的方法,包含了主要的密钥创建和初始换,和加解密的方法。每个方法都加了注释,这里就不详细解释了。

    #ifndef ACCP_SERVER_SDK_LIBS_ENCRYPTION_UTILS_H
    #define ACCP_SERVER_SDK_LIBS_ENCRYPTION_UTILS_H
    
    #include <string>
    #include <rsa.h>
    #include <cryptlib.h>
    #include <osrng.h>
    #include <assert.h>
    #include <blowfish.h>
    #include <filters.h>
    #include <modes.h>
    #include <boost/shared_ptr.hpp>
    #include "data_package_t.hpp"
    
    namespace my_utils {
        namespace utils {
            /**
             * 存放 blowfish 的密钥
             * data_key 为 key
             * data_iv 为 iv
             */
            struct blowfish_key_value {
                blowfish_key_value(std::size_t key_len = 0, std::size_t iv_len = 0)
                        : data_key(key_len), data_iv(iv_len) {}
                types::data_package_t data_key;
                types::data_package_t data_iv;
            };
    
            /**
             * 从数组导入rsa的 private key
             * @param private_key 需要导入的private key
             * @param _key_data   导入的数组
             * @return 执行是否成功
             */
            bool import_rsa_private_key_from_byte(CryptoPP::RSA::PrivateKey &private_key,
                                                  const types::data_package_t &_key_data);
    
            /**
             * 从数组导入rsa的 public key
             * @param public_key 需要 导入的 public key
             * @param _key_data 导入的数组
             * @return 执行是否成功
             */
            bool import_rsa_public_key_from_byte(CryptoPP::RSA::PublicKey &public_key,
                                                 const types::data_package_t &_key_data);
    
            /**
             * 导出rsa的private_key到数组
             * @param private_key 需要导出的private key
             * @param _key_data   导出的数组
             * @return 执行是否成功
             */
            bool export_rsa_private_key_to_byte(const CryptoPP::RSA::PrivateKey &private_key,
                                                types::data_package_t &_key_data);
    
            /**
             * 导出rsa的public_key到数组
             * @param public_key 需要导出的public_key
             * @param _key_data  导出的数组
             * @return 执行是否成功
             */
            bool export_rsa_public_key (const CryptoPP::RSA::PublicKey &public_key,
                                         types::data_package_t &_key_data);
    
            /**
             * 生成rsa密钥对
             * @param public_key  公钥
             * @param private_key 私钥
             * @param key_size    密钥的长度
             * @return 执行是否成功
             */
            bool generate_rsa_key(CryptoPP::RSA::PublicKey &public_key,
                                  CryptoPP::RSA::PrivateKey &private_key,
                                  unsigned int key_size);
    
            /**
             * RSA加密函数
             * @param public_key  公钥
             * @param str_data    需要加密的数据
             * @param cipher_data 加密后的数据
             * @return 执行是否成功
             */
            bool rsa_encrypt_std_string(CryptoPP::RSA::PublicKey &public_key,
                                        const std::string &str_data,
                                        my_utils::types::data_package_t &cipher_data);
    
            /**
             * RSA解密函数
             * @param private_key 私钥
             * @param raw_data    需要解密的数据
             * @param plain       解密后的数据
             * @return 执行是否成功
             */
            bool rsa_decrypt_byte_data(CryptoPP::RSA::PrivateKey &private_key,
                                       const my_utils::types::data_package_t &raw_data,
                                       std::string &plain);
    
            /**
             * 生成Blowfish 的密钥和iv
             * @param _key_value 密钥和iv
             * @return 执行是否成功
             */
            bool generate_blowfish_key(my_utils::utils::blowfish_key_value &_key_value);
    
            /**
             * 使用blowfish 加密数据
             * @param _key_value 密钥
             * @param plain      加密前的数据
             * @param cipher     加密后的数据
             * @return 执行是否成功
             */
            bool blowfish_encrypt_std_string(const blowfish_key_value &_key_value,
                                             const std::string &plain,
                                             std::string &cipher);
    
            /**
             * 使用blowfish 解密数据
             * @param _key_value 密钥
             * @param cipher     解密前的数据
             * @param plain      解密后的数据
             * @return 执行是否成功
             */
            bool blowfish_decrypt_byte_data(const blowfish_key_value &_key_value,
                                            const std::string &cipher,
                                            std::string &plain);
        }
    }
    
    
    #endif //ACCP_SERVER_SDK_LIBS_ENCRYPTION_UTILS_H
    
    

    encryption_utils.cpp 加解密的实现文件,主要参考了crypto的文档。

    
    #include "../include/encryption_utils.h"
    
    
    static CryptoPP::AutoSeededRandomPool g_rng;
    
    using namespace CryptoPP;
    
    bool my_utils::utils::import_rsa_private_key_from_byte(CryptoPP::RSA::PrivateKey &private_key,
                                                           const my_utils::types::data_package_t &_key_data) {
        try {
            CryptoPP::ByteQueue byte_queue;
            byte_queue.Put2(_key_data._arr_data.get(), _key_data._size_datalen, 0, false);
            private_key.Load(byte_queue.Ref());
            return true;
        } catch (const CryptoPP::Exception &e) {
            return false;
        }
    }
    
    bool ::my_utils::utils::import_rsa_public_key_from_byte(CryptoPP::RSA::PublicKey &public_key,
                                                            const my_utils::types::data_package_t &_key_data) {
    
        try {
            CryptoPP::ByteQueue byte_queue;
            byte_queue.Put2(_key_data._arr_data.get(), _key_data._size_datalen, 0, false);
            public_key.Load(byte_queue.Ref());
            return true;
        } catch (const CryptoPP::Exception &e) {
            return false;
        }
    }
    
    bool my_utils::utils::export_rsa_private_key_to_byte(const CryptoPP::RSA::PrivateKey &private_key,
                                                         my_utils::types::data_package_t &_key_data) {
        try {
            CryptoPP::ByteQueue byte_queue;
            private_key.Save(byte_queue);
            _key_data = my_utils::types::data_package_t(byte_queue.CurrentSize());
            byte_queue.Get(_key_data._arr_data.get(), _key_data._size_datalen);
            return true;
        } catch (const CryptoPP::Exception &) {
            return false;
        }
    }
    
    bool my_utils::utils::export_rsa_public_key(const CryptoPP::RSA::PublicKey &public_key,
                                                my_utils::types::data_package_t &_key_data) {
        try {
            CryptoPP::ByteQueue byte_queue;
            public_key.Save(byte_queue);
            _key_data = my_utils::types::data_package_t(byte_queue.CurrentSize());
            byte_queue.Get(_key_data._arr_data.get(), _key_data._size_datalen);
            return true;
        } catch (const CryptoPP::Exception &) {
            return false;
        }
    }
    
    bool my_utils::utils::generate_rsa_key(CryptoPP::RSA::PublicKey &public_key,
                                           CryptoPP::RSA::PrivateKey &private_key,
                                           unsigned int key_size) {
        try {
            CryptoPP::InvertibleRSAFunction parameters;
            parameters.GenerateRandomWithKeySize(g_rng, key_size);
    
            public_key = CryptoPP::RSA::PublicKey(parameters);
            private_key = CryptoPP::RSA::PrivateKey(parameters);
            return true;
        } catch (const CryptoPP::Exception &e) {
            return false;
        }
    }
    
    bool my_utils::utils::generate_blowfish_key(my_utils::utils::blowfish_key_value &_key_value) {
        try {
            _key_value = my_utils::utils::blowfish_key_value((std::size_t) CryptoPP::Blowfish::DEFAULT_KEYLENGTH,
                                                             (std::size_t) CryptoPP::Blowfish::BLOCKSIZE);
            g_rng.GenerateBlock(_key_value.data_key._arr_data.get(), _key_value.data_key._size_datalen);
            g_rng.GenerateBlock(_key_value.data_iv._arr_data.get(), _key_value.data_key._size_datalen);
            return true;
        } catch (const CryptoPP::Exception &e) {
            return false;
        }
    }
    
    
    bool my_utils::utils::rsa_encrypt_std_string(CryptoPP::RSA::PublicKey &public_key,
                                                 const std::string &str_data,
                                                 my_utils::types::data_package_t &cipher_data) {
        try {
    
            CryptoPP::SecByteBlock plaintext(str_data.length());
            memcpy(plaintext.data(), str_data.c_str(), str_data.length());
    
            CryptoPP::RSAES_OAEP_SHA_Encryptor encryptor(public_key);
    
            assert(0 != encryptor.FixedMaxPlaintextLength());
            assert(str_data.length() <= encryptor.FixedMaxPlaintextLength());
    
            size_t ecl = encryptor.CiphertextLength(plaintext.size());
            CryptoPP::SecByteBlock ciphertext(ecl);
    
            encryptor.Encrypt(g_rng, plaintext, plaintext.size(), ciphertext);
    
            cipher_data = my_utils::types::data_package_t(ecl);
    
            memcpy(cipher_data._arr_data.get(), ciphertext.data(), ciphertext.size());
    
            return true;
        } catch (const CryptoPP::Exception &e) {
            return false;
        }
    }
    
    bool my_utils::utils::rsa_decrypt_byte_data(CryptoPP::RSA::PrivateKey &private_key,
                                                const my_utils::types::data_package_t &raw_data,
                                                std::string &plain) {
    
        try {
            CryptoPP::SecByteBlock ciphertext(raw_data._size_datalen);
            assert(raw_data._size_datalen <= ciphertext.size());
            memcpy(ciphertext.data(), raw_data._arr_data.get(), raw_data._size_datalen);
    
            // Decrypt
            CryptoPP::RSAES_OAEP_SHA_Decryptor decryptor(private_key);
    
            // Now that there is a concrete object, we can validate
            assert(0 != decryptor.FixedCiphertextLength());
            assert(ciphertext.size() <= decryptor.FixedCiphertextLength());
    
            size_t dpl = decryptor.MaxPlaintextLength(ciphertext.size());
            assert(0 != dpl);
            CryptoPP::SecByteBlock recovered(dpl);
    
            // Paydirt
            CryptoPP::DecodingResult result = decryptor.Decrypt(g_rng,
                                                                ciphertext, ciphertext.size(), recovered);
    
            // More sanity checks
            assert(result.isValidCoding);
            assert(result.messageLength <=
                   decryptor.MaxPlaintextLength(ciphertext.size()));
    
            plain = std::string((char *) recovered.data(), result.messageLength);
            return true;
        } catch (const CryptoPP::Exception &e) {
            return false;
        }
    }
    
    
    bool my_utils::utils::blowfish_encrypt_std_string(const my_utils::utils::blowfish_key_value &_key_value,
                                                      const std::string &plain,
                                                      std::string &cipher) {
    
    
        try {
            CBC_Mode<Blowfish>::Encryption e;
            e.SetKeyWithIV(_key_value.data_key._arr_data.get(),
                           _key_value.data_key._size_datalen,
                           _key_value.data_iv._arr_data.get());
    
    
            StringSource(plain, true,
                         new StreamTransformationFilter(e,
                                                        new StringSink(cipher)
                         )
            );
    
            return true;
        } catch (const CryptoPP::Exception &e) {
            return false;
        }
    }
    
    bool my_utils::utils::blowfish_decrypt_byte_data(const my_utils::utils::blowfish_key_value &_key_value,
                                                     const std::string &cipher,
                                                     std::string &plain) {
        try {
            CBC_Mode<Blowfish>::Decryption d;
            d.SetKeyWithIV(_key_value.data_key._arr_data.get(),
                           _key_value.data_key._size_datalen,
                           _key_value.data_iv._arr_data.get());
    
            StringSource s(cipher, true,
                           new StreamTransformationFilter(d,
                                                          new StringSink(plain)
                           )
            );
    
            return true;
        } catch (const CryptoPP::Exception &e) {
            return false;
        }
    }
    
    
    

    下面是测试代码:

    #include "../include/encryption_utils.h"
    
    using namespace std;
    using namespace my_utils;
    using namespace my_utils::utils;
    using namespace my_utils::types;
    using namespace boost;
    
    /**
     * RSA加密解密测试代码
     */
    void rsa_encrypt_test() {
    
        bool b_result = false;
        CryptoPP::RSA::PublicKey _rsa_publickey;
        CryptoPP::RSA::PrivateKey _rsa_privatekey;
        // 生成密钥
        generate_rsa_key(_rsa_publickey, _rsa_privatekey, 1024);
    
        data_package_t cipher_data;
        // 加密前的数据
        std::string str_data("Hello World");
        // 执行加密操作
        b_result = rsa_encrypt_std_string(_rsa_publickey, str_data, cipher_data);
        assert(b_result);
        // 导出加密数据
        std::string outdata((char *) cipher_data._arr_data.get(), cipher_data._size_datalen);
        data_package_t cipher_data_1(outdata.size());
        memcpy(cipher_data_1._arr_data.get(), outdata.c_str(), outdata.size());
        // 测试密钥的导出和导入
        data_package_t _output_private_key;
        b_result = export_rsa_private_key_to_byte(_rsa_privatekey, _output_private_key);
        assert(b_result);
        data_package_t _output_public_key;
        b_result = export_rsa_public_key(_rsa_publickey, _output_public_key);
        assert(b_result);
    
        CryptoPP::RSA::PublicKey _rsa_second_publickey;
        CryptoPP::RSA::PrivateKey _rsa_second_privatekey;
    
        b_result = import_rsa_private_key_from_byte(_rsa_second_privatekey, _output_private_key);
        assert(b_result);
    
        b_result = import_rsa_public_key_from_byte(_rsa_second_publickey, _output_public_key);
        assert(b_result);
    
        std::string plain;
        // 执行解密操作
        b_result = rsa_decrypt_byte_data(_rsa_second_privatekey, cipher_data_1, plain);
        assert(b_result);
        assert(plain == str_data);
    }
    
    /**
     * blowfish 加密解密测试
     */
    void blowfish_encrtpt_test() {
        bool b_result = false;
        blowfish_key_value _key_value;
        // 生成密钥
        b_result = generate_blowfish_key(_key_value);
        assert (b_result);
        // 加密前的密钥
        std::string plain_1("Hello World");
        std::string cipher_1;
        // 执行加密操作
        b_result = blowfish_encrypt_std_string(_key_value, plain_1, cipher_1);
        assert(b_result);
        std::string plain_2;
        // 执行解密操作
        b_result = blowfish_decrypt_byte_data(_key_value, cipher_1, plain_2);
        assert(b_result);
        assert(plain_2 == plain_1);
    }
    

    相关文章

      网友评论

          本文标题:c++下RSA和BLOWFISH加解密-使用Crypto库

          本文链接:https://www.haomeiwen.com/subject/xbfrgttx.html