c++调用openssl对文件加解密

c++调用openssl对文件加解密

  • 1.OpenSSL简介
  • 2.使用 EVP 库实现 DES 和 AES 加密
    • EVP_EncryptUpdate 函数参数详解
      • EVP 库的AES 算法的cbc模式
  • 3.DEC加密的ecb模式 (没有EVP方式效率高)

1.OpenSSL简介

OpenSSL库是由C语言实现,整个软件包大概可以分成三个主要的功能部分:密码算法库、SSL协议库以及应用程序。OpenSSL是目前主流的基于密码学的安全开发包,提供的功能相当强大和全面,包括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用。
  OpenSSL库具有以下优点:1.功能全面,支持大部分主流密码算法、相关标准协议和SSL协议;2.开放源代码,可信任,能根据自己需要进行修改,对技术人员有借鉴和研究的价值;3.具备应用程序,既能直接使用,也可方便地进行二次开发;4.免费,也可用作非商业用途;5.应用广泛且持续更新

openssl库的下载和环境配置这里就不描述了。。。

2.使用 EVP 库实现 DES 和 AES 加密

Openssl EVP(high-level cryptographic functions) 提供了丰富的密码学中的各种函数,包括各种对称算法、摘要算法以及签名/验签算法。下面重点学习使用 DES 和 AES 两种对称加密算法。
  在使用 EVP 库进行对称加密时,通常需要创建一个EVP_CIPHER_CTX 结构体对象,并通过一系列函数对其进行初始化、配置,最终进行加密操作。常用的 EVP_CIPHER_CTX 结构体初始化函数为 EVP_CIPHER_CTX_new() 和 EVP_CIPHER_CTX_init()。
  EVP_CIPHER_CTX_new() 函数在堆上为 EVP_CIPHER_CTX 结构体分配内存空间,并将其所有成员变量初始化为 0;EVP_CIPHER_CTX_init() 函数则用于初始化 EVP_CIPHER_CTX结构体对象的成员变量。
  在加密操作完成后,需要通过调用 EVP_CIPHER_CTX_cleanup 函数释放 EVP_CIPHER_CTX结构体对象的内存空间,以免内存泄漏。下面为EVP库的初始化代码:

  1. EVP_CIPHER_CTX∗ ctx = EVP_CIPHER_CTX_new() ; //结构体对象ctx分配内存空间
  2. EVP_CIPHER_CTX_init( ctx ) ; //初始化结构体对象ctx
  3. EVP_CIPHER_CTX_cleanup( ctx ) ; //释放结构体对象空间

EVP_EncryptUpdate 函数参数详解

在 DES 加密中,常见的 EVP_CIPHER 对象的类型有 EVP_des_ecb(),进行一次 des 的 ecb 模式加密;EVP_des_cbc()、EVP_des_ede3_cbc()。

在 AES 加密中,常见的 EVP_CIPHER 对象类型有:

EVP_aes_128_cbc、EVP_aes_192_cbc、EVP_aes_256_cbc:分别表示使用 AES 算法和 CBC 模式进行加密和解密,密钥长度分别为
128、192 和 256 位。
EVP_aes_128_ecb、EVP_aes_192_ecb、EVP_aes_256_ecb:分别表示使用 AES 算法和 ECB 模式进行加密和解密,密钥长度分别为 128、192 和 256 位。
EVP_aes_128_gcm、EVP_aes_256_gcm:分别表示使用 AES 算法和 GCM 模式进行加密和解密,密钥长度分别为 128 和 256 位。

下面列出两种加密方式

EVP 库的AES 算法的cbc模式

加密:将test.jpg加密另存为test.enc

#include <iostream>
#include <fstream>
#include <string>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>using namespace std;#define READ_BUFF 1024
int main()
{const unsigned char key[32] = "0123456789abcdef";const unsigned char iv[16] = "edcba9876543210";//创建一个 EVP_CIPHER_CTX 对象EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();//选择加密算法const EVP_CIPHER *cipher = EVP_aes_256_cbc();//初始化加密上下文EVP_CIPHER_CTX_init(ctx);//设置密钥和偏移量EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv);std::ifstream in("test.jpg", ifstream::in | ios::binary);if (!in.is_open()) {std::cerr << "Failed to open file." << std::endl;return 1;}ofstream out("test.enc", ios::binary);if (!out) {perror("fopen");return 1;}//加密文件内容并写入新文件int out_len = 0;char inbuf[READ_BUFF];char outbuf[READ_BUFF + 520];while (!in.eof()){in.read(inbuf, READ_BUFF);int read_len = in.gcount();if (!EVP_EncryptUpdate(ctx, (unsigned char*)outbuf, &out_len, (unsigned char*)inbuf, read_len)){cerr << "EVP_EncryptUpdate failed" << endl;return -1;}out.write(outbuf, out_len);}in.close();if (!EVP_EncryptFinal_ex(ctx, (unsigned char*)outbuf, &out_len)){cerr << "EVP_EncryptFinal_ex failed" << endl;return -1;}out.write(outbuf, out_len);out.close();//销毁加密上下文EVP_CIPHER_CTX_cleanup(ctx);return 0;
}

解密:将test.enc解密另存为test2.jpg,解密用到的keyiv需同加密一致

#include <iostream>
#include <fstream>
#include <string>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>using namespace std;#define READ_BUFF 1024
int main()
{const unsigned char key[32] = "0123456789abcdef";const unsigned char iv[16] = "edcba9876543210";EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();const EVP_CIPHER *cipher = EVP_aes_256_cbc();EVP_CIPHER_CTX_init(ctx);EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv);// 读取加密文件内容std::ifstream in("test.enc", ifstream::in | ios::binary);if (!in.is_open()) {std::cerr << "failed to open encode file." << std::endl;return 1;}ofstream out("test2.jpg", ios::binary);if (!out) {cerr << "failed to create decode file!" << endl;return -1;}//解密文件内容并写入int out_len = 0;char inbuf[READ_BUFF];char outbuf[READ_BUFF + 520];while (!in.eof()){in.read(inbuf, READ_BUFF);int read_len = in.gcount();if (!EVP_DecryptUpdate(ctx, (unsigned char*)outbuf, &out_len, (unsigned char*)inbuf, read_len)){cerr << "EVP_DecryptUpdate failed" << endl;return 1;}out.write(outbuf, out_len);}in.close();if (!EVP_DecryptFinal_ex(ctx, (unsigned char*)outbuf, &out_len)){cerr << "EVP_DecryptFinal_ex failed" << endl;return 1;}out.write(outbuf, out_len);out.close();//销毁解密上下文EVP_CIPHER_CTX_cleanup(ctx);return 0;
}

3.DEC加密的ecb模式 (没有EVP方式效率高)

加密封装

/* 
*DES加密 ecb模式
*in_buffer:输入的明文
*in_length:明文长度
*key:密匙
*/
std::string des_encrypt(const char* in_buffer, int in_length,const std::string &key)
{std::string cipherText; // 密文DES_cblock keyEncrypt;memset(keyEncrypt, 0, 8);// 构造补齐后的密钥  if (key.length() <= 8)memcpy(keyEncrypt, key.c_str(), key.length());elsememcpy(keyEncrypt, key.c_str(), 8);// 密钥置换  DES_key_schedule keySchedule;DES_set_key_unchecked(&keyEncrypt, &keySchedule);// 循环加密,每8字节一次  const_DES_cblock inputText;DES_cblock outputText;std::vector<unsigned char> vecCiphertext;unsigned char tmp[8];for (int i = 0; i < in_length / 8; i++){memcpy(inputText, in_buffer + i * 8, 8);DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);memcpy(tmp, outputText, 8);vecCiphertext.insert(vecCiphertext.end(), tmp, tmp + 8);}if (in_length % 8 != 0){int tmp1 = in_length / 8 * 8;int tmp2 = in_length - tmp1;memset(inputText, 0, 8);memcpy(inputText, in_buffer + tmp1, tmp2);DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);memcpy(tmp, outputText, tmp2);vecCiphertext.insert(vecCiphertext.end(), tmp, tmp + tmp2);}cipherText.clear();cipherText.assign(vecCiphertext.begin(), vecCiphertext.end());return cipherText;
}

解密封装

/*
*DES解密 ecb模式
*in_buffer:输入的密文
*in_length:密文长度
*key:密匙
*/
std::string des_decrypt(const char* in_buffer, int in_length, const std::string &key)
{std::string clearText; // 明文  DES_cblock keyEncrypt;memset(keyEncrypt, 0, 8);if (key.length() <= 8)memcpy(keyEncrypt, key.c_str(), key.length());elsememcpy(keyEncrypt, key.c_str(), 8);DES_key_schedule keySchedule;DES_set_key_unchecked(&keyEncrypt, &keySchedule);const_DES_cblock inputText;DES_cblock outputText;std::vector<unsigned char> vecCleartext;unsigned char tmp[8];for (int i = 0; i < in_length / 8; i++){memcpy(inputText, in_buffer + i * 8, 8);DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);memcpy(tmp, outputText, 8);vecCleartext.insert(vecCleartext.end(), tmp, tmp + 8);}if (in_length % 8 != 0){int tmp1 = in_length / 8 * 8;int tmp2 = in_length - tmp1;memset(inputText, 0, 8);memcpy(inputText, in_buffer + tmp1, tmp2);DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);memcpy(tmp, outputText, tmp2);vecCleartext.insert(vecCleartext.end(), tmp, tmp + tmp2);}clearText.clear();clearText.assign(vecCleartext.begin(), vecCleartext.end());return clearText;
}

调用方式

int main(int argc, char **argv)
{//加密{std::ifstream file("test.jpg", ifstream::in | ios::binary);if (!file.is_open()) {std::cerr << "Failed to open file." << std::endl;return 1;}std::string srcText;while (!file.eof()) {char buffer[1024];file.read(buffer, 1024);srcText.append(buffer, file.gcount());}file.close();std::string encryptText;std::string encryptHexText;std::string decryptText;std::string desKey = "12345";encryptText = des_encrypt(srcText.data(), srcText.length(), desKey);ofstream out("test.enc", ios::binary);if (!out) {perror("fopen");return 1;}out.write(encryptText.data(), encryptText.length());out.close();}//解密{// 打开加密文件std::ifstream file_out("test.enc", ios::binary);if (!file_out.is_open()) {std::cerr << "Failed to open file." << std::endl;return 1;}std::string content;while (!file_out.eof()){char buffer[1024];file_out.read(buffer, 1024);content.append(buffer, file_out.gcount());}file_out.close();decryptText = des_decrypt(content.data(), content.length(), desKey);ofstream out2("test2.jpg", ios::binary);if (!out) {perror("fopen2");return 1;}out2.write(decryptText.data(), decryptText.length());out2.close();}system("pause");return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/180536.shtml

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

相关文章

20世纪30年代的大危机

背景 1929年9月&#xff0c;美国财政部部长安德鲁梅隆向公众保证“现在没有担心的理由&#xff0c;这一繁荣的高潮将会继续下去”。 当时流行的一首儿歌&#xff1a;“梅隆拉响汽笛&#xff0c;胡佛敲起钟&#xff0c;华尔街发出信号&#xff0c;美国往地狱里冲&#xff01;”…

Elasticsearch:向量搜索 (kNN) 实施指南 - API 版

作者&#xff1a;Jeff Vestal 本指南重点介绍通过 HTTP 或 Python 使用 Elasticsearch API 设置 Elasticsearch 以进行近似 k 最近邻 (kNN) 搜索。 对于主要使用 Kibana 或希望通过 UI 进行测试的用户&#xff0c;请访问使用 Elastic 爬虫的语义搜索入门指南。你也可以参考文章…

聚观早报 |红魔9 Pro开卖;真我GT5 Pro定档

【聚观365】11月29日消息 红魔9 Pro开卖 真我GT5 Pro定档 一加12镜头细节公布 Redmi K70 Pro将搭载夜枭算法 苹果Vision Pro头显下月量产 红魔9 Pro开卖 红魔电竞旗舰最新力作——红魔9 Pro系列正式发布。作为一款全能电竞旗舰&#xff0c;该机搭载了第三代骁龙8移动平台…

计网Lesson4 - 计算机组网模型

文章目录 计算机的连接方式1. 两台计算机的互联2. 多台计算机的互联&#xff08;旧式&#xff09;3. 多台计算机的互联 --- 集线器&#xff08;Hub&#xff09;4. 网桥5. 多台计算机的互联 --- 交换器&#xff08;Switch&#xff09; 计算机的连接方式 1. 两台计算机的互联 网…

唯创知音WT2003H系列MP3录音语音芯片:高精度ADC与DAC,强大IO驱动能力成就音频卓越

在音频领域里&#xff0c;高精度和强大的驱动能力一直是工程师们追求的目标。唯创知音的WT2003H系列MP3录音芯片恰好满足了这一需求&#xff0c;该芯片具备16 bit高精度的ADC及DAC功能&#xff0c;大功率的IO驱动能力&#xff0c;能够直接驱动64mA&#xff0c;为电子产品带来卓…

【互联网小趣味】身为程序员哪一个瞬间让你最奔溃?

目录 编译错误&#xff1a; 逻辑错误&#xff1a; 调试问题&#xff1a; 复杂的需求&#xff1a; 时间压力&#xff1a; 与他人合作问题&#xff1a; 编译错误&#xff1a; 你在编写代码时&#xff0c;突然遇到了一堆红色的错误提示&#xff0c;但是你无法立即找到问题所…

web框架,django,路由控制,视图层(补充)

web框架 是什么&#xff1f; web 框架是什么---》别人帮咱们写了一些基础代码---》我们只需要在固定的位置写固定的代码--》就能实现一个web应用 Web框架&#xff08;Web framework&#xff09;是一种开发框架&#xff0c;用来支持动态网站、网络应用和网络服务的开发。这大多…

JSTL标签 参考手册

前言 JSTL标签库&#xff0c;是日常开发经常使用的&#xff0c;也是众多标签中性能最好的。把常用的内容&#xff0c;放在这里备份一份&#xff0c;随用随查。尽量做到不用查&#xff0c;就可以随手就可以写出来。这算是Java程序员的基本功吧&#xff0c;一定要扎实。 JSTL全名…

C#多线程创建及线程的同步

需求&#xff1a;有时为了能分时的调用多个任务运行&#xff0c;因此需要考虑多线程的编程方式 操作步骤如下&#xff1a; 1&#xff09;创建线程并开启线程 Thread thread0 new Thread(() > DoWork0(0)); thread0.Start(); 2&#xff09;编写线程函数 static void Do…

“目标函数“(Objective Function)和“损失函数“(Loss Function)有什么区别

"目标函数"&#xff08;Objective Function&#xff09;和"损失函数"&#xff08;Loss Function&#xff09;通常在机器学习和优化问题中使用&#xff0c;它们在某些上下文中可以是相同的&#xff0c;但也有一些区别。 目标函数&#xff08;Objective Func…

漏洞扫描-德迅云安全漏洞扫描服务

漏洞扫描是指基于漏洞数据库&#xff0c;通过扫描等手段对指定的远程或者本地计算机系统的安全脆弱性进行检测&#xff0c;发现可利用漏洞的一种安全检测的行为。 漏洞扫描的主要目的是发现系统、网络或应用程序中可能存在的安全漏洞和缺陷&#xff0c;以便及时修复这些漏洞和缺…

python实验3 石头剪刀布游戏

实验3&#xff1a;石头剪刀布游戏 一、实验目的二、知识要点图三、实验1. 石头剪刀布2. 实现大侠个人信息 一、实验目的 了解3类基本组合数据类型。理解列表概念并掌握Python中列表的使用。理解字典概念并掌握Python中字典的使用。运用jieba库进行中文分词并进行文本词频统计。…

C/C++ 发送与接收HTTP/S请求

HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于传输超文本的协议。它是一种无状态的、应用层的协议&#xff0c;用于在计算机之间传输超文本文档&#xff0c;通常在 Web 浏览器和 Web 服务器之间进行数据通信。HTTP 是由互联网工程任务组&#xff08;IETF…

上海亚商投顾:沪指震荡反弹 汽车产业链掀涨停潮

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数昨日震荡反弹&#xff0c;北证50指数跌超4%&#xff0c;近50只北交所个股跌超10%。 新能源车产业链掀…

深度学习点云质量增强方法综述

好久没更新博客了&#xff0c;后面计划重启博客&#xff0c;空闲时分享一下学习心得&#xff0c;包括但不局限于点云编码/压缩、插帧、质量增强。这次&#xff0c;推荐一篇综述论文。 期刊&#xff1a;《中国图象图形学报》2023年第28卷第11期 作者&#xff1a;陈建文1, 赵丽丽…

JSONP解决跨域问题

前言 本文主要讲解跨域问题以及解决跨域问题的方案之一JSONP的实现方式。 什么是跨域 全称为Cross-Origin Resource Sharing,简单来说请求的客户端和服务端的端口、域名、协议中的任意一个有不一样的地方在URL的展示中&#xff0c;那么就会出现这个跨域问题。 它产生的原因…

不同路径 II(力扣LeetCode)动态规划

不同路径 II 题目描述 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。…

Vue3自定义指令(directive)

Vue2自定义指令&#xff08;directive&#xff09; Vue3自定义指令&#xff08;directive&#xff09;

【Android Jetpack】Hilt 依赖注入框架

文章目录 依赖注入DaggerHiltKoin添加依赖项Hilt常用注解的含义HiltAndroidAppAndroidEntryPointInjectModuleInstallInProvidesEntryPoint Hilt组件生命周期和作用域如何使用 Hilt 进行依赖注入 依赖注入 依赖注入是一种软件设计模式&#xff0c;它允许客户端从外部源获取其依…

智能井盖传感器怎么监测井盖倾斜?

城市道路上的井盖是常见的安全隐患&#xff0c;由于井盖质量不过关、安装不合理等原因导致的井盖位移或倾斜等事故&#xff0c;每年都处于不断增加的状态。为了减少此类案件的发生并维护社会治安&#xff0c;国家相关部门已经制定了多项政策法规对井盖进行统一监管。鼓励各个城…