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

用 OpenSSL 库实现 3DES(三重DES)加密

用 OpenSSL 库实现 3DES(三重DES)加密操作。以下是代码的详细解析:

1. 包含头文件和命名空间:

#include <iostream>
#include <openssl/evp.h>
#include <openssl/err.h>
  • #include : 引入 C++ 标准库,用于输入输出操作。
  • #include <openssl/evp.h>: 引入 OpenSSL 的 EVP (Envelope) API,这是 OpenSSL 提供的高级加解密接口。
  • #include <openssl/err.h>: 引入 OpenSSL 错误处理头文件,用于打印 OpenSSL 错误。

2. 定义 main 函数并初始化数据:

int main(int argc, char *argv[])
{const unsigned char data[] = "1234567812345678"; // 输入int data_size = sizeof(data) - 1;                // 计算数据长度,不包括'\0'cout << "data_size = " << data_size << endl;
  • data[]: 需要加密的输入数据(字符串 “1234567812345678”)。
  • data_size: 计算数据长度,这里使用 sizeof(data) - 1,因为 sizeof(data) 会包括末尾的 ‘\0’ 字符,因此需要减去 1。

3. 定义加密参数:

unsigned char out[1024] = {0};                      // 输出
unsigned char key[] = "123456789012345678901234"; // 24 字节的密钥(3DES)
unsigned char iv[8] = {0};                          // 8 字节的初始化向量(IV)
  • out[]: 用来存储加密后的输出数据。
  • key[]: 3DES 使用的密钥,3DES 算法需要 24 字节的密钥。此处密钥被设置为 - “123456789012345678901234”,总长度为 24 字节。
  • iv[]: 初始化向量(IV),用于加密过程中的随机化,长度为 8 字节。

4. 选择加密算法和打印加密参数:

// 三重DES 3DES 算法
auto cipher = EVP_des_ede3_cbc();
// 获取算法的分组大小
int block_size = EVP_CIPHER_block_size(cipher);
int key_size = EVP_CIPHER_key_length(cipher);
int iv_size = EVP_CIPHER_iv_length(cipher);
cout << "block_size = " << block_size << endl;
cout << "key_size = " << key_size << endl;
cout << "iv_size = " << iv_size << endl;
  • EVP_des_ede3_cbc(): 使用 OpenSSL 的 EVP API 来选择三重 DES(3DES)加密算法,这里使用的是 3DES 的 CBC 模式(密码分组链接模式)。
  • EVP_CIPHER_block_size(cipher): 获取加密算法的分组大小(即块大小)。对于 3DES,块大小为 8 字节。
  • EVP_CIPHER_key_length(cipher): 获取密钥的长度。对于 3DES,密钥长度为 24 字节。
  • EVP_CIPHER_iv_length(cipher): 获取 IV(初始化向量)的长度。对于 3DES,IV 长度为 8 字节。

5. 初始化加解密上下文并开始加密:

// 加解密上下文
auto ctx = EVP_CIPHER_CTX_new();
// 加密算法初始化int re = EVP_CipherInit_ex(ctx, cipher, nullptr, key, iv, 1); // 1表示加密
if (!re)
{ERR_print_errors_fp(stderr);getchar();return -1;
}
cout << "EVP_CipherInit success!" << endl;
  • EVP_CIPHER_CTX_new(): 创建一个新的加解密上下文,用于存储加解密的状态。
  • EVP_CipherInit_ex(ctx, cipher, nullptr, key, iv, 1): 初始化加解密上下文,传入所选择的加密算法、密钥、初始化向量和加密模式。这里的 1 表示加密模式(解密时应该传 0)。如果初始化失败,程序会打印错误信息并退出。

6. 设置填充方式:

 // 设置填充方式(默认是 PKCS7)EVP_CIPHER_CTX_set_padding(ctx, EVP_PADDING_PKCS7);
  • EVP_CIPHER_CTX_set_padding(ctx, EVP_PADDING_PKCS7): 设置加密过程中的填充方式。默认使用 PKCS7 填充方式,即使加密数据不是块大小的整数倍,也会进行填充,使其对齐到块大小。

7. 执行加密操作:

int out_size = 0;
EVP_CipherUpdate(ctx, out, &out_size, data, data_size);
cout << "EVP_CipherUpdate size: " << out_size << endl;
  • EVP_CipherUpdate(ctx, out, &out_size, data, data_size): 进行加密操作,将输入数据 data 加密后写入 out 中,out_size 存储实际加密后的字节数。

8. 处理最后的填充块:

  int padding_size = 0;EVP_CipherFinal_ex(ctx, out + out_size, &padding_size);cout << "padding_size = " << padding_size << endl;out_size += padding_size;
  • EVP_CipherFinal_ex(ctx, out + out_size, &padding_size): 获取加密结果的最后一块数据(如果有填充)。填充是为了保证加密数据大小是块大小的整数倍。
  • padding_size: 返回填充数据的大小。将其加到 out_size 中,得到总的加密数据大小。

9. 打印加密后的数据:

   cout << "Encrypted data: ";for (int i = 0; i < out_size; ++i){printf("%02x", out[i]); // 以十六进制打印每个字节}cout << endl;
  • 打印加密后的数据。由于输出的是字节数据,直接打印可能显示为乱码,因此使用 printf(“%02x”, out[i]) 以十六进制格式打印每个字节。

10. 释放上下文并结束程序:

   // 释放上下文EVP_CIPHER_CTX_free(ctx);getchar();return 0;
}
  • EVP_CIPHER_CTX_free(ctx): 释放加解密上下文,以避免内存泄漏。
  • getchar(): 用于暂停程序,等待用户输入,便于查看加密结果。

总结:

该程序使用 OpenSSL 库的 EVP API 对数据进行 3DES 加密,使用 CBC 模式。通过初始化密钥、初始化向量(IV)和加密上下文来执行加密,并处理填充。最后,程序以十六进制格式打印加密后的数据。

完整代码

#include <iostream>
#include <openssl/evp.h>
#include <openssl/err.h>// _CRT_SECURE_NO_WARNINGS
// #include <openssl/applink.c>
using namespace std;int main(int argc, char *argv[])
{const unsigned char data[] = "1234567812345678"; // 输入int data_size = sizeof(data) - 1;                // 计算数据长度,不包括'\0'cout << "data_size = " << data_size << endl;unsigned char out[1024] = {0};                    // 输出unsigned char key[] = "123456789012345678901234"; // 24 字节的密钥(3DES)unsigned char iv[8] = {0};                        // 8 字节的初始化向量(IV)// 三重DES 3DES 算法auto cipher = EVP_des_ede3_cbc();// 获取算法的分组大小int block_size = EVP_CIPHER_block_size(cipher);int key_size = EVP_CIPHER_key_length(cipher);int iv_size = EVP_CIPHER_iv_length(cipher);cout << "block_size = " << block_size << endl;cout << "key_size = " << key_size << endl;cout << "iv_size = " << iv_size << endl;// 加解密上下文auto ctx = EVP_CIPHER_CTX_new();// 加密算法初始化int re = EVP_CipherInit_ex(ctx, cipher, nullptr, key, iv, 1); // 1表示加密if (!re){ERR_print_errors_fp(stderr);getchar();return -1;}cout << "EVP_CipherInit success!" << endl;// 设置填充方式(默认是 PKCS7)EVP_CIPHER_CTX_set_padding(ctx, EVP_PADDING_PKCS7);int out_size = 0;// 只处理分组大小得到数据, 如果取消自动填充,多余数据丢弃EVP_CipherUpdate(ctx, out, &out_size, data, data_size);cout << "EVP_CipherUpdate size: " << out_size << endl;// 取出最后一块数据(需要填充的),或者是 padding 补充的数据int padding_size = 0;EVP_CipherFinal_ex(ctx, out + out_size, &padding_size);cout << "padding_size = " << padding_size << endl;out_size += padding_size;// 打印加密后的数据cout << "Encrypted data: ";for (int i = 0; i < out_size; ++i){printf("%02x", out[i]); // 以十六进制打印每个字节}cout << endl;// 释放上下文EVP_CIPHER_CTX_free(ctx);getchar();return 0;
}
http://www.xdnf.cn/news/13619.html

相关文章:

  • CKA考试知识点分享(10)---NetworkPolicy
  • 【Git】TortiseGit设置过滤上传文件
  • 神经网络:深度剖析过拟合、欠拟合及其泛化能力提升策略
  • 【学习笔记】HTTP
  • P2834 纸币问题 3
  • 讲一件Java虚拟线程
  • 小白理财 - 入门第一课
  • 扁平风格职场商务通用PPT模版分享
  • AI支持下的-ArcGIS数据处理、空间分析、可视化及多案例综合应用
  • Java多线程实现之同步方法详解
  • Win10重装系统 (重生篇:我在华强修电脑)
  • 用python玩转大语言模型——从 RNN 到文本生成大语言模型的奇幻之旅
  • SpringBoot学习day2-前后端的交互搭建以及跨域问题、拦截过滤器问题的解决
  • 理解系统交互:UML时序图
  • 驭码CodeRider 2.0 产品体验:在VSCode安装并创建一个雷电小游戏
  • Django项目QQ授权登录报错:redirect uri is illegal(100010) 解决方法
  • 深度学习小项目合集之音频语音识别
  • docker-compose搭建eureka-server和zipkin
  • ubuntu 安装 JDK8
  • 安信可(云知声蜂鸟US516P6)SDK开发学习---log日志打印子系统模块
  • 云原生安全实践:CI/CD流水线集成DAST工具
  • 【PostgreSQL系列】PostgreSQL WAL 目录配置
  • 力扣HOT100之贪心算法:45. 跳跃游戏 II
  • 零基础设计模式——行为型模式 - 备忘录模式
  • 前端实现ios26最新液态玻璃效果!
  • Leetcode-11 2 的幂
  • 前端实战:用 HTML+JS 打造可拖动图像对比滑块,提升视觉交互体
  • Reactive-Resume:重构你的简历编写体验
  • window 显示驱动开发-如何查询视频处理功能(六)
  • (LeetCode 动态规划(基础版) )337. 打家劫舍 III (深度优先搜索dfs)