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

来源:互联网 发布:没有网站怎么做seo 编辑:程序博客网 时间:2024/04/28 17:59

工作需要使用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);}
0 0
原创粉丝点击