#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;
}
学习笔记:boost iostream filter封装openssl EVP
最新推荐文章于 2022-04-02 17:27:40 发布