当前位置: 首页 > news >正文

openssl加解密-干货分享

0.需要包含的头文件和预定义常量
 

#include <openssl/rand.h>#include <fstream>#include <openssl/aes.h>#include <openssl/rand.h>// 加密密钥和初始化向量(IV)长度#define AES_KEY_LENGTH 32#define AES_IV_LENGTH 16

1.密钥的生成与管理

    unsigned char key[32];if (RAND_bytes(key, sizeof(key)) != 1) {// 处理错误}// 使用自己的加密密钥// 将 key 转换为十六进制字符串std::string key_str;for (size_t i = 0; i < sizeof(key); i++) {char hex[3];snprintf(hex, sizeof(hex), "%02x", key[i]);key_str += hex;}std::cout << "key_str=" << key_str << std::endl;

将加密密钥保存到文件:

// 将加密密钥保存到文件void saveKeyToFile(const char* filename, const AES_KEY* key) {std::ofstream file(filename, std::ios::binary);if (file.is_open()) {// 写入轮数file.write(reinterpret_cast<const char*>(&key->rounds), sizeof(key->rounds));// 写入密钥调度表file.write(reinterpret_cast<const char*>(key->rd_key), sizeof(key->rd_key));file.close();std::cout << "Encryption key saved to file: " << filename << std::endl;} else {std::cerr << "Error opening file for writing: " << filename << std::endl;}}

从文件中加载加密密钥:
 

// 从文件中加载加密密钥void loadKeyFromFile(const char* filename, AES_KEY* key) {std::ifstream file(filename, std::ios::binary);if (file.is_open()) {// 读取轮数file.read(reinterpret_cast<char*>(&key->rounds), sizeof(key->rounds));// 读取密钥调度表file.read(reinterpret_cast<char*>(key->rd_key), sizeof(key->rd_key));file.close();std::cout << "Encryption key loaded from file: " << filename << std::endl;} else {std::cerr << "Error opening file for reading: " << filename << std::endl;}}

2.加密
 

    // 使用AES-256加密算法void encryptFile(const std::string &inputFilename, const std::string &outputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));//AES_set_encrypt_key(ckey, AES_KEY_LENGTH * 8, &aesKey);//(const unsigned char *)key.c_str()AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);// 将加密密钥保存到文件//saveKeyToFile("encryption_key.bin", &aesKey);std::cout << "key :\t" << key << std::endl;// 生成随机IVunsigned char iv[AES_IV_LENGTH];RAND_bytes(iv, AES_IV_LENGTH);iv[AES_IV_LENGTH-1]='\0';// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);std::cout << "ivBackup :\t" << ivBackup << std::endl;std::ifstream inputFile(inputFilename, std::ios::binary);std::ofstream outputFile(outputFilename, std::ios::binary);outputFile.write(reinterpret_cast<const char *>(iv), AES_IV_LENGTH);unsigned char inBuffer[16], outBuffer[16];int num = 0;static int testi=0;while (inputFile.good()) { // 检查文件是否有效inputFile.read(reinterpret_cast<char *>(inBuffer), 16);// 获取实际读取的字节数int bytesRead = inputFile.gcount();if (inputFile.gcount() > 0) { // 检查实际读取的字节数memcpy( iv , ivBackup, AES_BLOCK_SIZE);AES_cfb128_encrypt(inBuffer, outBuffer, 16, &aesKey, iv, &num, AES_ENCRYPT);// 重置 IV//memcpy(iv, ivBackup, AES_IV_LENGTH);/* //if(testi<=1)是为了检查,检查解密出来的第一段16字节内容是否跟加密前的一样if(testi<=1) {//std::cout << "inBuffer :\t" << inBuffer << std::endl;std::cout << "encryptFile, inBuffer:\n";for (int i = 0; i < 16; i++) {printf("%02x", inBuffer[i]); // 打印十六进制形式}std::cout << "\n";std::cout << "encrypted data:\t";for (int i = 0; i < 16; i++) {printf("%02x", outBuffer[i]); // 打印十六进制形式}std::cout << std::endl;memcpy( iv , ivBackup, AES_BLOCK_SIZE);unsigned char decrypt_outBuffer[16];AES_cfb128_encrypt(outBuffer, decrypt_outBuffer, 16, &aesKey, iv, &num, AES_DECRYPT);//std::cout << "decrypt_outBuffer :\t" << decrypt_outBuffer << std::endl;std::cout << "encryptFile, decrypt_outBuffer:\n";for (int i = 0; i < 16; i++) {printf("%02x", decrypt_outBuffer[i]); // 打印十六进制形式}std::cout << "\n";testi++;}*/outputFile.write(reinterpret_cast<const char *>(outBuffer), 16);}}}

这个写法有个很大的问题,把输入的文件内容认为是16字节的整数倍,这样是不合理的!修正后的写法:

    void encryptFile(const std::string &inputFilename, const std::string &outputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);// 生成随机 IVunsigned char iv[AES_IV_LENGTH];RAND_bytes(iv, AES_IV_LENGTH);// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);std::cout << "key :\t" << key << std::endl;std::cout << "ivBackup :\t";for (int i = 0; i < AES_IV_LENGTH; i++) {printf("%02x", ivBackup[i]);}std::cout << std::endl;std::ifstream inputFile(inputFilename, std::ios::binary);std::ofstream outputFile(outputFilename, std::ios::binary);outputFile.write(reinterpret_cast<const char *>(iv), AES_IV_LENGTH);unsigned char inBuffer[AES_BLOCK_SIZE], outBuffer[AES_BLOCK_SIZE];int num = 0;//static int testi=0;while (inputFile.good()) {inputFile.read(reinterpret_cast<char *>(inBuffer), AES_BLOCK_SIZE);// 获取实际读取的字节数int bytesRead = inputFile.gcount();if (bytesRead > 0) {// 拷贝 IV//memcpy(iv, ivBackup, AES_BLOCK_SIZE);// 加密AES_cfb128_encrypt(inBuffer, outBuffer, bytesRead, &aesKey, iv, &num, AES_ENCRYPT);// 输出加密数据outputFile.write(reinterpret_cast<const char *>(outBuffer), bytesRead);// if(testi<=1) {//             // 重置 IV//             memcpy(iv, ivBackup, AES_BLOCK_SIZE);//             // 解密,为了测试//             unsigned char decrypt_outBuffer[AES_BLOCK_SIZE];//             AES_cfb128_encrypt(outBuffer, decrypt_outBuffer, bytesRead, &aesKey, iv, &num, AES_DECRYPT);//             // 打印信息,为了测试//             std::cout << "inBuffer:\n";//             for (int i = 0; i < bytesRead; i++) {//                 printf("%02x", inBuffer[i]);//             }//             std::cout << "\n";//             std::cout << "encrypted data:\t";//             for (int i = 0; i < bytesRead; i++) {//                 printf("%02x", outBuffer[i]);//             }//             std::cout << std::endl;//             std::cout << "decrypt_outBuffer:\n";//             for (int i = 0; i < bytesRead; i++) {//                 printf("%02x", decrypt_outBuffer[i]);//             }//             std::cout << "\n";//             testi++;// }}}}

3.解密

    void decryptFile(const std::string &inputFilename, const std::string &outputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));//unsigned char ckey[] = "helloworldkey\0";AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);//AES_set_decrypt_key(ckey, AES_KEY_LENGTH * 8, &aesKey);//(const unsigned char *)key.c_str()/* set the encryption key *///AES_set_decrypt_key(ckey, 128, &aesKey);// 加载加密密钥//loadKeyFromFile("encryption_key.bin", &aesKey);std::cout << "key :\t" << key << std::endl;std::ifstream inputFile(inputFilename, std::ios::binary);std::ofstream outputFile(outputFilename, std::ios::binary);// 从文件中读取IVunsigned char iv[AES_IV_LENGTH];inputFile.read(reinterpret_cast<char *>(iv), AES_IV_LENGTH);// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);std::cout << "ivBackup :\t" << ivBackup << std::endl;unsigned char inBuffer[16], outBuffer[16];int num = 0;static int testi=0;while (inputFile.good()) {inputFile.read(reinterpret_cast<char *>(inBuffer), 16);if (inputFile.gcount() > 0) { // 检查实际读取的字节数memcpy( iv , ivBackup, AES_BLOCK_SIZE);AES_cfb128_encrypt(inBuffer, outBuffer, 16, &aesKey, iv, &num, AES_DECRYPT);//nullptr// 重置 IV//memcpy(iv, ivBackup, AES_IV_LENGTH);if(testi<=1) {//std::cout << "inBuffer :\t" << inBuffer << std::endl;std::cout << "encrypted data:\t";for (int i = 0; i < 16; i++) {printf("%02x", inBuffer[i]); // 打印十六进制形式}std::cout << std::endl;//std::cout << "outBuffer :\t" << outBuffer << std::endl;std::cout << "decryptFile, outBuffer:\n";for (int i = 0; i < 16; i++) {printf("%02x", outBuffer[i]); // 打印十六进制形式}std::cout << "\n";testi++;}outputFile.write(reinterpret_cast<char *>(outBuffer), 16);}}}

这个写法有个很大的问题,把输入的文件内容认为是16字节的整数倍,这样是不合理的!修正后的写法:

void decryptFile(const std::string &inputFilename, const std::string &outputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);// 打开输入文件std::ifstream inputFile(inputFilename, std::ios::binary);if (!inputFile) {std::cerr << "Error opening input file." << std::endl;return;}// 打开输出文件std::ofstream outputFile(outputFilename, std::ios::binary);if (!outputFile) {std::cerr << "Error opening output file." << std::endl;return;}// 从文件中读取 IVunsigned char iv[AES_IV_LENGTH];inputFile.read(reinterpret_cast<char *>(iv), AES_IV_LENGTH);// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);std::cout << "ivBackup :\t";for (int i = 0; i < AES_IV_LENGTH; i++) {printf("%02x", ivBackup[i]);}std::cout << std::endl;unsigned char inBuffer[AES_BLOCK_SIZE], outBuffer[AES_BLOCK_SIZE];int num = 0;while (inputFile.good()) {inputFile.read(reinterpret_cast<char *>(inBuffer), AES_BLOCK_SIZE);// 获取实际读取的字节数int bytesRead = inputFile.gcount();if (bytesRead > 0) {// 拷贝 IV//memcpy(iv, ivBackup, AES_BLOCK_SIZE);// 解密AES_cfb128_encrypt(inBuffer, outBuffer, bytesRead, &aesKey, iv, &num, AES_DECRYPT);// 输出解密数据outputFile.write(reinterpret_cast<char *>(outBuffer), bytesRead);}}}

4.加密和解密接口的调用

encryptFile("./models/test.jpg", "./models/encrypted_cornerModel.crypt", key_str);
decryptFile("./models/encrypted_cornerModel.crypt", "./models/decrypt_test.jpg", key_str);
encryptFile("./models/patternModel.onnx", "./models/encrypted_patternModel.crypt", key_str);
decryptFile("./models/encrypted_patternModel.crypt", "./models/decrypt_patternModel.onnx", key_str);
encryptFile("./models/cornerModel.onnx", "./models/encrypted_cornerModel.crypt", key_str);
decryptFile("./models/encrypted_cornerModel.crypt", "./models/decrypt_cornerModel.onnx", key_str);

5.解密出来的内容,不保存到文件,而是直接保存到内存缓冲区后,再将内存缓冲区的模型数据传递给 readNet 接口

void decryptAndLoadModel(const std::string &inputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);// 打开输入文件std::ifstream inputFile(inputFilename, std::ios::binary);if (!inputFile) {std::cerr << "Error opening input file." << std::endl;return;}// 从文件中读取 IVunsigned char iv[AES_IV_LENGTH];inputFile.read(reinterpret_cast<char *>(iv), AES_IV_LENGTH);// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);// 定义内存缓冲区用于存储解密的模型数据std::vector<unsigned char> decryptedModelBuffer;unsigned char inBuffer[AES_BLOCK_SIZE], outBuffer[AES_BLOCK_SIZE];int num = 0;while (inputFile.good()) {inputFile.read(reinterpret_cast<char *>(inBuffer), AES_BLOCK_SIZE);// 获取实际读取的字节数int bytesRead = inputFile.gcount();if (bytesRead > 0) {// 解密AES_cfb128_encrypt(inBuffer, outBuffer, bytesRead, &aesKey, iv, &num, AES_DECRYPT);// 存储解密数据到内存缓冲区decryptedModelBuffer.insert(decryptedModelBuffer.end(), outBuffer, outBuffer + bytesRead);}}// 使用 OpenCV 读取解密后的模型数据cv::Mat modelDataMat(1, decryptedModelBuffer.size(), CV_8U, decryptedModelBuffer.data());// 将解密后的模型数据传递给 readNet 接口cv::dnn::Net neuralNet = cv::dnn::readNetFromONNX(modelDataMat);// 使用 neuralNet 对象进行后续操作,如推理等// ...
}

在加密中,IV(Initialization Vector,初始化向量)和 Key(密钥)是两个重要的概念,它们通常用于对数据进行加密和解密。

  1. Initialization Vector(IV,初始化向量): IV 是在对称加密中使用的固定长度的随机值。它的作用是增强加密算法的安全性,以防止在相同密钥下对相同的明文进行多次加密时产生相同的密文输出。

    IV 与密钥不同,IV 不需要保密,通常会与密文一起传输。对于每个独立的消息,IV 都应该是唯一的,但不需要保密。在开始加密之前,IV 会与密钥一起输入到加密算法中,以确保对相同的明文使用相同的密钥和 IV 时,每次得到的密文都是不同的。

  2. Key(密钥): 密钥是用于加密和解密数据的机密值。在对称加密中,加密和解密使用相同的密钥。保持密钥的机密性对于加密的安全性至关重要。只有知道密钥的人才能解密数据。

    密钥应该是足够长且具有足够的随机性,以防止被暴力破解。安全的加密算法强调了密钥的安全性和保密性,因为知道密钥的人可以解密被加密的数据。

IV 和密钥的选择对于加密的安全性至关重要。合适的 IV 长度和随机性以及安全的密钥管理对于确保加密系统的安全性非常重要。IV 和密钥的选择取决于所使用的加密算法和具体的安全需求。

http://www.lryc.cn/news/240317.html

相关文章:

  • 【考研数据结构代码题7】求一元多项式之和
  • python避坑指南(更新中)
  • 可以远程控制电脑桌面的软件有哪些?
  • 洛谷 P1250 种树
  • java大视频在线预览(支持断点下载)
  • OpenCV入门10——特征点检测与匹配
  • 教育机构拒绝“数据陷阱”,群硕将英孚新一代教学管理系统搬上桌
  • 小辰的智慧树(差分+前缀和)
  • Windows如何使用key登录Linux服务器
  • k8s无法删除pv,pvc问题
  • 基于框架的线性回归
  • 万宾科技智能井盖传感器使用方式,具有什么效果?
  • 13.什么是Spring beans?
  • 算法通关村第十二关|白银|字符串经典基础面试题
  • Spring框架学习 -- 读取和存储Bean对象
  • APM工具skywalking部署
  • MFC打开可执行文件exe
  • css实现原生form表单label必填选项红色*样式,以及js控制必填校验
  • 10_6 input输入子系统,流程解析
  • 竞赛选题 题目:垃圾邮件(短信)分类 算法实现 机器学习 深度学习 开题
  • Web前端—移动Web第三天(移动Web基础、rem、less、综合案例—极速问诊)
  • MySQL--慢查询(一)
  • 【大神支招】3步,打造一张BI报表
  • 【Linux】文件操作
  • (动手学习深度学习)第13章 实战kaggle竞赛:狗的品种识别
  • 自定义注解+AOP
  • Ribbon
  • git -1
  • 基于SSM+Vue的鲜花销售系统/网上花店系统
  • 安卓:Android Studio4.0~2023中正确的打开Android Device Monitor