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.mzph.cn/news/163542.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

竞赛选题 题目:垃圾邮件(短信)分类 算法实现 机器学习 深度学习 开题

文章目录 1 前言2 垃圾短信/邮件 分类算法 原理2.1 常用的分类器 - 贝叶斯分类器 3 数据集介绍4 数据预处理5 特征提取6 训练分类器7 综合测试结果8 其他模型方法9 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于机器学习的垃圾邮件分类 该项目…

3分钟使用 WebSocket 搭建属于自己的聊天室(WebSocket 原理、应用解析)

文章目录 WebSocket 的由来WebSocket 是什么WebSocket 优缺点优点缺点 WebSocket 适用场景主流浏览器对 WebSocket 的兼容性WebSocket 通信过程以及原理建立连接具体过程示例Sec-WebSocket-KeySec-WebSocket-Extensions 数据通信数据帧帧头&#xff08;Frame Header&#xff09…

组合数学学习

指数生成函数可以与排列结合在一起&#xff0c;而幂级数和 组合结合在一起 如果要进行计算的值不是一个具体的值&#xff0c;那么就要考虑生成函数

Windows如何使用key登录Linux服务器

场景&#xff1a;因为需要回收root管理员权限&#xff0c;禁止root用户远程登录&#xff0c;办公环境只允许普通用户远程登录&#xff0c;且不允许使用密码登录。 一、生成与配置ssh-key 1.使用root管理员权限登录到目标系统。 2.创建一个新的普通用户&#xff0c;和设置密码用…

Java,File类与IO流,File类与IO流的概述

File的概述&#xff1a; File定义在java.io包下。 一个File对象代表硬盘或网络中可能存在的一个文件或者文件目录&#xff08;俗称文件夹&#xff09;&#xff0c;与平台无关。 File能新建、删除、重命名文件和目录&#xff0c;但File不能访问文件内容本身。如果需要访问文件…

用uniapp在微信小程序实现画板(电子签名)功能

目录 一、效果展示 二、插件推荐与引入 三、代码具体应用 四、h5端将base64转换为url 一、效果展示 二、插件推荐与引入 手写板、签字板&#xff1b;<zwp-draw-pad /> - DCloud 插件市场 这个在微信小程序引入时内容简单&#xff0c;且涉及的方法很多&#xff0c;…

【C/C++】排序算法代码实现

这里&#xff0c;汇总了常见的排序算法具体代码实现。使用C语言编写。 排序算法实现 插入排序冒泡排序选择排序快速排序希尔排序归并排序 插入排序 #include <stdio.h> #include <stdlib.h>void InsertSort(int arr[],int n){int i,j,temp;for(i 1;i < n;i){ …

Pinia状态持久化——插件pinia-plugin-persistedstate

pinia-plugin-persistedstate 旨在通过一致的 API 为 Pinia Store 提供持久化存储。如果希望保存一个完整的 Store&#xff0c;或者需要细粒化配置 storage 和序列化的方式&#xff0c;该插件都提供了相应的功能&#xff0c;并且可以在想要持久化的 Store 上使用相同的配置。 …

Python 异常的传递性

实例 这里就简单用2个function来演示一下异常的传递性 func1 这里num 1/0明显是一个ZeroDivisionError错误&#xff0c;作为演示 def func1():print("fun1 开始执行")num 1 / 0print("func1 结束执行") func2 def func2():print("func2 开始执…

tomcat国密ssl测试

文章目录 程序包准备部署配置访问测试 程序包准备 下载 tomcat8.5 https://www.gmssl.cn/gmssl/index.jsp 下载 tomcat 国密组件及证书 本次测试所有的程序文件均已打包&#xff0c;可以直接 点击下载 部署配置 自行完成 完成centos 的jdk配置。 部署tomcat,将 gmssl4t.jar…

数字孪生农村供水工程平台:为乡村振兴注入新活力

随着科技的不断进步&#xff0c;数字孪生技术逐渐成为各行业创新发展的重要驱动力。在水利领域&#xff0c;数字孪生农村供水平台以其独特的优势&#xff0c;为农村供水系统带来了革命性的变革。本文将为您详细介绍数字孪生农村供水平台的核心特点及优势&#xff0c;带您领略智…

深度学习常见激活函数:ReLU,sigmoid,Tanh,softmax,Leaky ReLU,PReLU,ELU整理集合,应用场景选择

文章目录 1、ReLU 函数&#xff08;隐藏层中是一个常用的默认选择&#xff09;1.1 优点1.2 缺点 2、sigmoid 函数2.1 优点2.2 缺点 3、Tanh 函数3.1 优点3.2 缺点 4、softmax 函数&#xff08;多分类任务最后一层都会使用&#xff09;5、Leaky ReLU 函数5.1 优点5.2 缺点 6、PR…

mongo DB -- aggregate分组查询后字段展示

一、分组查询 在mongoDB中可以使用aggregate中的$group操作对集合中的文档进行分组,但是查询后的数据不显示其他字段,只显示分组字段 aggregate进行分组示例 db.collection.aggregate([{$group: {_id: "$field"}},]) 查询后显示 展开只显示两个字段 二、显示所有字段…

APM工具skywalking部署

一 整体架构 整个架构&#xff0c;分成上、下、左、右四部分&#xff1a; 上部分 Agent &#xff1a;负责从应用中&#xff0c;收集链路信息&#xff0c;发送给 SkyWalking OAP 服务器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。而我们目前采用的是&…

Rust - cargo项目里多个二进制binary crate的编译运行

目录 foo - Cargo.toml - src - - main.rs - - bin - - - other-bin.rs将除默认入口文件外待作为二进制crate处理的文件放在src/bin目录下 方法一&#xff1a; 命令行增加配置项 --bin xxx cargo run --bin foo // 注意! 这里是包名&#xff0c;不是main cargo run --bin o…

SQL基础理论篇(九):存储过程

文章目录 简介存储过程的形式定义一个存储过程使用delimiter定义语句结束符存储过程中的三种参数类型流控制语句 存储过程的优缺点参考文献 简介 存储过程Stored Procedure&#xff0c;SQL中的另一个重要应用。 前面说的视图&#xff0c;只能勉强跟编程中的函数相似&#xff…

MySQL -- JDBC

1、JDBC是什么&#xff1a; 是SUN公司制定的一套接口(interface)。接口都有调用者和实现者。面向接口调用、面向接口写实现类&#xff0c;这都属于面向接口编程。 2、在使用JDBC的六个步骤&#xff1a; 1.注册驱动&#xff08;告诉Java程序&#xff0c;即将连接的是哪个品牌…

业务系统上云后,如何满足员工移动办公快速访问业务系统的需求?

在企业业务上云的大趋势下&#xff0c;SaaS应用、云端办公协同工具等多种远程办公应用系统开始大规模普及&#xff0c;企业员工可以随时随地访问云上业务数据。然而现实情况却十分“打脸”&#xff0c;企业随时随地要访问云上业务的需求越迫切&#xff0c;问题就越大。由于多种…

算法通关村第十二关|白银|字符串经典基础面试题

1.反转问题 1.1 反转字符串 原题&#xff1a;力扣344. 要求原地修改。 public void reverseString(char[] s) {if (s null || s.length() 0) {return;}int n s.length;for (int left 0, right n - 1; left < right; left, right--) {char temp s[left];s[left] s…

小程序订阅消息

wx.requestSubscribeMessage({tmplIds: [2IdqlWrqSbjAurzIuW8imeK-ftS8gbhYdZ0icdE],success(res) {console.log(res);// 处理用户授权结果},fail(err) {console.error(err);// 处理授权请求失败}});