C++使用openssl实现aes加解密,其中加密是string到文件,解密是文件到string,切合项目背景

本文介绍了如何利用C++结合OpenSSL库实现AES加解密操作。加密过程将字符串写入文件,解密则从文件读取并还原为字符串。同时,为增强密码安全性,采用了MD5对用户输入的密码进行处理,确保密码长度固定。

代码

  • 使用md5对于用户输入的密码进行保护,也使得密码的长度固定
  • crypto_util.h
#pragma once

#include <string>

namespace hsm{
namespace mgmt{

void get_md5_digest(const std::string &data,uint8_t result[16]);

void aes_encrypt_to_file(const std::string &file_name,
                         const std::string &password,const std::string &data);

std::string aes_decrypt_from_file(const std::string &file_name,
                                  const std::string &password);

}//namespace mgmt
}//namespace hsm
  • crypto_util.c
#include "crypto_util.h"

#include <cstring>
#include <fstream>
#include <memory>
#include <sstream>

#include <openssl/aes.h>
#include <openssl/md5.h>

namespace hsm{
namespace mgmt{

void get_md5_digest(const std::string &data,uint8_t result[16]){
    MD5_CTX md5_ctx{};
    MD5_Init(&md5_ctx);
    MD5_Update(&md5_ctx,data.c_str(),data.length());
    MD5_Final(result,&md5_ctx);
}
/**
 * @brief generate a valid aes key from input password
 *
 * @note AES only support keys with length 128/192/256bits
 * @note this implementation use md5 as a method to fix the password
 */
std::unique_ptr<AES_KEY> get_aes_key(const std::string &password,int flag){
    auto aes_key = std::make_unique<AES_KEY>();
    uint8_t md5_key[16]{};
    get_md5_digest(password,md5_key);
    if (flag == AES_ENCRYPT){
        AES_set_encrypt_key(md5_key,sizeof(md5_key)*8,aes_key.get());
    } else if (flag == AES_DECRYPT){
        AES_set_encrypt_key(md5_key,sizeof(md5_key)*8,aes_key.get());
    }
    return aes_key;
}

void aes_encrypt_to_file(const std::string &file_name,
                         const std::string &password,const std::string &data){
    std::ofstream f{file_name,std::ios::binary};
    auto aes_key = get_aes_key(password,AES_ENCRYPT);
    uint8_t aes_buffer[AES_BLOCK_SIZE];
    auto input_offset = reinterpret_cast<const uint8_t *>(data.c_str());

    //encrypt blocks
    for (size_t i = 0; i < data.length() / AES_BLOCK_SIZE; ++i) {
        AES_encrypt(input_offset,aes_buffer,aes_key.get());
        f.write(reinterpret_cast<const char *>(aes_buffer),sizeof(aes_buffer));

        input_offset += AES_BLOCK_SIZE;
    }
    //write rest od data to file
    auto rest_input_length = data.length() % AES_BLOCK_SIZE;
    if (rest_input_length > 0 ){
        f.write(reinterpret_cast<const char *>(input_offset),rest_input_length);
    }
    f.close();
}
std::string aes_decrypt_from_file(const std::string &file_name,
                                  const std::string &password){
    std::ifstream f{file_name,std::ios::binary};
    std::stringstream ss;
    ss << f.rdbuf();
    auto data = ss.str();

    auto aes_key = get_aes_key(password,AES_DECRYPT);
    std::string result(data.length(),'0');
    auto input_offset = reinterpret_cast<const uint8_t *>(data.c_str());
    auto output_offset = reinterpret_cast<uint8_t *>(&result[0]);

    //decrypt blocks
    for (size_t i = 0;i < data.length() / AES_BLOCK_SIZE;i++){
        AES_decrypt(input_offset,output_offset,aes_key.get());
        input_offset += AES_BLOCK_SIZE;
        output_offset += AES_BLOCK_SIZE;
    }
    //decrypt rest of data
    auto rest_input_length = data.length() % AES_BLOCK_SIZE;
    if (rest_input_length > 0 ){
        std::memcpy(output_offset,input_offset,
                    rest_input_length + 1);
    }
    return result;
}

}//namespace mgmt
}//namespace hsm

测试

#include "common/filesystem.h"
#include "util/crypto_util.h"

#include <gtest/gtest.h>

namespace hsm {
namespace test {

using namespace mgmt;

TEST(AES, EncryptAndDecrypt) {
  std::string tmp_file = common::generate_temp_file_name();

  std::string password = "1234567";
  std::string data = "12345678901234567890, hello, world!";

  aes_encrypt_to_file(tmp_file, password, data);
  ASSERT_EQ(aes_decrypt_from_file(tmp_file, password), data);
}

} // namespace test
} // namespace hsm

 

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值