学习笔记:boost iostream filter封装openssl EVP

#include <openssl/evp.h>  //for EVP_xxx函数族
#include <openssl/aes.h>  //for openssl 

#include <boost/iostreams/concepts.hpp>  //for output_filter_tag etc..
#include <boost/iostreams/filter/stdio.hpp>  //for iostreams::write

#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>

namespace boost {
    namespace iostreams {
        namespace example {
            
            class aes_cbc128_encryption {
            public:

                typedef char char_type;
                struct category : output_filter_tag,  //支持输出式过滤器
                                  flushable_tag,  //支持flush
                                  multichar_tag   //支持多字节写入, 不适用单字节写入的put函数
                { };  //支持flushable_tag的filter,需要在此定义,boost库没有合适的。

                //encrypt_type取值为:AES_ENCRYPT或者AES_DECRYPT
                explicit aes_cbc128_encryption(char* key,char* iv,int encrypt_type)
                { 
                    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
                    ctx_ = boost::shared_ptr<EVP_CIPHER_CTX>(ctx, EVP_CIPHER_CTX_free);

                    memcpy(key_, key, 16);
                    memcpy(iv_, iv, 16);

                    EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL, encrypt_type);

                    OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16);
                    OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16);

                    /* Now we can set key and IV */
                    EVP_CipherInit_ex(ctx, NULL, NULL, key_, iv_, encrypt_type);

                    /* Allow enough space in output buffer for additional block */
                    outbuf_.reset(new unsigned char[1024 + EVP_MAX_BLOCK_LENGTH]);

                    is_flushed_ = false;
                }

                aes_cbc128_encryption& operator=(const aes_cbc128_encryption&) = delete;

                //多字节写入
                template<typename Sink>
                std::streamsize write(Sink& dest, const char* s, std::streamsize n)
                {
                    EVP_CIPHER_CTX* ctx = ctx_.get();
                    unsigned char* outbuf = outbuf_.get();
                    int outlen=0;
                    unsigned char* inbuf = (unsigned char*)s;
                    int inlen = n;

                    //outlen一般是16的倍数,说明EVP会攒足16个字节倍数的数据,才处理和输出。剩余的字节需要调用EVP_CipherFinal_ex处理
                    if (!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen))
                    {
                        throw std::exception("EVP_CipherUpdate Error!!");
                    }
                    iostreams::write(dest, (const char*)outbuf, outlen);

                    return n;
                }

                //flush,把EVP保留的剩余字节写入Sink
                template<typename Sink>
                bool flush(Sink& dest)
                {
                    if (!is_flushed_) 
                    {
                        is_flushed_ = true;
                        
                        EVP_CIPHER_CTX* ctx = ctx_.get();
                        unsigned char* outbuf = outbuf_.get();
                        int outlen = 0;
                        if (!EVP_CipherFinal_ex(ctx, outbuf, &outlen))
                        {
                            throw std::exception("EVP_CipherFinal_ex Error!!");
                        }
                        iostreams::write(dest, (const char*)outbuf, outlen);
                    }
                    return true;
                }
                
            private:

                boost::shared_ptr<EVP_CIPHER_CTX> ctx_;  //句柄类,对象拷贝后,使用智能指针管理

                unsigned char key_[16];
                unsigned char iv_[16];

                boost::shared_array<unsigned char> outbuf_;

                bool is_flushed_; //防止flush被调用多次
           };

        }
    }
} // End namespace boost::iostreams:example

#include <vector>
#include <boost/iostreams/filtering_stream.hpp>

int main(int argc, char *argv[]) {

    std::vector<char> cyperVec;
    char* src = "#123456789abcdef$%^";

    {
        boost::iostreams::filtering_ostream fos;
        fos.push(boost::iostreams::example::aes_cbc128_encryption("This Is My Key8", "This Is Init Vec", AES_ENCRYPT));
        fos.push(boost::iostreams::back_inserter(cyperVec));
        fos.write(src, strlen(src)+1);
        boost::iostreams::close(fos);
    }

    std::string plainStr;
    {
        boost::iostreams::filtering_ostream fos;
        fos.push(boost::iostreams::example::aes_cbc128_encryption("This Is My Key8", "This Is Init Vec", AES_DECRYPT));
        fos.push(boost::iostreams::back_inserter(plainStr));
        fos.write(cyperVec.data(), cyperVec.size());
        boost::iostreams::close(fos); 
    }
    

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值