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.pswp.cn/news/163542.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/163542.shtml
英文地址,請注明出處:http://en.pswp.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);// 處理授權請求失敗}});