OpenSSL之API编程 - C/C++实现AES、DES、3DES、SM4对称加密算法

文章介绍

  • 本文章介绍了OpenSSL计算对称加解密算法(AES、DES、3DES、SM4等)的相关接口,并使用C语言实现了AES和SM4加解密。

对称加解密算法

  • 对称加密与非对称加密算法

OpenSSL介绍

  • openssl是一个功能丰富且自包含的开源安全工具箱。它提供的主要功能有:SSL协议实现、对称/非对称加密算法、大数运算、非对称算法密钥生成、ASN.1编解码库、证书请求(PKCS10)编解码、数字证书编解码、CRL编解码、OCSP协议、数字证书验证、PKCS7标准实现和PKCS12个人数字证书格式实现等功能。
  • openssl采用C语言作为开发语言,这使得它具有优秀的跨平台性能。openssl支持Linux、UNIX、windows、Mac等平台。
  • github源码地址
  • openssl_1.1.1u工程: 不知道如何集成Openssl工程的话, 可以下载我集成好的测试工程使用。

相关API

  • EVP_CIPHER_CTX_new

    •   /**  @brief  创建加解密算法上下文*  @return 成功: 返回一个指向新分配的 EVP_CIPHER_CTX 结构体的指针*          失败: 返回NULL*/EVP_CIPHER_CTX *EVP_CIPHER_CTX_new();
      
  • EVP_EncryptInit_ex

    •   /**  @brief  初始化一个加密上下文*  @param  [IN]  ctx   EVP_CIPHER_CTX_new 接口创建的上下文*  @param  [IN]  cipher  加密算法类型, 常用的有以下几种*                           AES算法*                               EVP_aes_128_ecb() *                               EVP_aes_256_ecb() *                               EVP_aes_128_cbc() *                               EVP_aes_256_cbc()*                           *                           DES算法*                               EVP_des_ecb()*                               EVP_des_cbc()**                           3DES算法*                               EVP_des_ede3_ecb()*                               EVP_des_ede3_cbc() **                           SM4算法*                               EVP_sm4_ecb() *                               EVP_sm4_cbc()       *  @param  [IN]  impl  用于指定一个特定的加密引擎实现, 通常设置为NULL*  @param  [IN]  key   加密密钥*                           AES算法 - AES算法支持16个字节、24个字节以及32个字节的密钥长度。*                                   - 根据选择的不同加密算法传入不同的密钥长度*                           DES算法  - 长度8个字节*                           3DES算法 - 长度为24个字节*                           SM4算法  - 长度为16个字节*  @param  [IN]  iv    初始化向量, ecb模式不需要指定,可传入NULL*                           AES算法  - 长度为16个字节*                           DES算法  - 长度8个字节*                           3DES算法 - 长度为8个字节*                           SM4算法  - 长度为16个字节*  @return 成功返回1*/int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,const unsigned char *key, const unsigned char *iv);
      
  • EVP_EncryptUpdate

    •   /**  @brief  分块加密*  @param  [IN]   ctx   EVP_CIPHER_CTX_new 接口创建的上下文*  @param  [OUT]  out   加密后的数据*  @param  [OUT]  outl  加密后的数据长度*  @param  [IN]   in    原始数据*  @param  [IN]   inl   原始数据长度*  @return 成功返回1         */int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);
      
  • EVP_EncryptFinal_ex

    •   /**  @brief  完成加密过程的最后阶段*  @param  [IN]   ctx   EVP_CIPHER_CTX_new 接口创建的上下文*  @param  [OUT]  out   加密后的数据*  @param  [OUT]  outl  加密后的数据长度*  @return 成功返回1         */int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
      
  • EVP_DecryptInit_ex

    •       /**  @brief  初始化一个解密上下文。参数详细说明参考 EVP_EncryptInit_ex 接口*  @param  [IN]  ctx     EVP_CIPHER_CTX_new 接口创建的上下文*  @param  [IN]  cipher  解密算法类型      *  @param  [IN]  impl    用于指定一个特定的解密引擎实现, 通常设置为NULL*  @param  [IN]  key     解密密钥*  @param  [IN]  iv      初始化向量, ecb模式不需要指定,可传入NULL*  @return 成功返回1*/int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,const unsigned char *key, const unsigned char *iv);
      
  • EVP_DecryptUpdate

    •   /**  @brief  分块解密*  @param  [IN]   ctx   EVP_CIPHER_CTX_new 接口创建的上下文*  @param  [OUT]  out   解后的数据*  @param  [OUT]  outl  解密后的数据长度*  @param  [IN]   in    需要解密的密文数据*  @param  [IN]   inl   需要解密的密文数据长度*  @return 成功返回1         */int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);
      
  • EVP_DecryptFinal_ex

    •   /**  @brief  完成解密过程的最后阶段*  @param  [IN]   ctx   EVP_CIPHER_CTX_new 接口创建的上下文*  @param  [OUT]  out   解密后的数据*  @param  [OUT]  outl  解密后的数据长度*  @return 成功返回1         */int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
      
  • EVP_CIPHER_CTX_free

    •   /**  @brief  释放加解密算法上下文*  @param  [IN]   ctx   EVP_CIPHER_CTX_new 接口创建的上下文*/void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
      

代码示例

  • AES、DES、3DES、SM4加解密使用的是同一套API,这里只演示了AES和SM4加解密,其它算法参考API接口自己实现即可。

AES加解密

  •   #include <openssl/evp.h>#include <stdio.h>#include <string.h>int main(){EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();if (ctx == NULL){printf("EVP_CIPHER_CTX_new failed.\n");return -1;}//加密算法初始化char* key = "1234567812345678";char* ivec = "abcdefghabcdefgh";	if(EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, (const unsigned char*)key, (const unsigned char*)ivec) != 1){printf("EVP_EncryptInit_ex failed.\n");return -1;}	int encDataLen = 0;int encDataLenTemp = 0;//加密操作char* srcData = "hello world";unsigned char encData[1024] = { 0 };if(EVP_EncryptUpdate(ctx, encData, &encDataLen, (const unsigned char*)srcData, strlen((char*)srcData)) != 1){printf("EVP_EncryptUpdate failed.\n");return -1;}//结束加密操作if(EVP_EncryptFinal_ex(ctx, encData + encDataLen, &encDataLenTemp) != 1){printf("EVP_EncryptFinal_ex failed.\n");return -1;}encDataLen += encDataLenTemp;// 16进制格式打印加密数据for(int i = 0; i < encDataLen; i++){printf("%.02x", encData[i]);}printf("\n");// 解密算法初始化if(EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, (const unsigned char*)key, (const unsigned char*)ivec) != 1){printf("EVP_DecryptInit_ex failed.\n");return -1;}int outlen = 0;unsigned char decData[1024] = { 0 };int decDataLen = 0;int decDataLenTemp = 0;//解密操作if(EVP_DecryptUpdate(ctx, decData, &decDataLen, encData, encDataLen) != 1){printf("EVP_DecryptUpdate failed.\n");return -1;}//结束解密操作if(EVP_DecryptFinal_ex(ctx, decData + decDataLen, &decDataLenTemp) != 1){printf("EVP_DecryptFinal_ex failed.\n");return -1;}decDataLen += decDataLenTemp;decData[decDataLen] = '\0';printf("decData = %s\n", decData);EVP_CIPHER_CTX_free(ctx);	return 0;}
    

SM4加解密

  •   #include <openssl/evp.h>#include <stdio.h>#include <string.h>int main(){EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();if (ctx == NULL){printf("EVP_CIPHER_CTX_new failed.\n");return -1;}//加密算法初始化char* key = "1234567812345678";char* ivec = "abcdefghabcdefgh";	if(EVP_EncryptInit_ex(ctx, EVP_sm4_cbc(), NULL, (const unsigned char*)key, (const unsigned char*)ivec) != 1){printf("EVP_EncryptInit_ex failed.\n");return -1;}	int encDataLen = 0;int encDataLenTemp = 0;//加密操作char* srcData = "hello world";unsigned char encData[1024] = { 0 };if(EVP_EncryptUpdate(ctx, encData, &encDataLen, (const unsigned char*)srcData, strlen((char*)srcData)) != 1){printf("EVP_EncryptUpdate failed.\n");return -1;}//结束加密操作if(EVP_EncryptFinal_ex(ctx, encData + encDataLen, &encDataLenTemp) != 1){printf("EVP_EncryptFinal_ex failed.\n");return -1;}encDataLen += encDataLenTemp;// 16进制格式打印加密数据for(int i = 0; i < encDataLen; i++){printf("%.02x", encData[i]);}printf("\n");// 解密算法初始化if(EVP_DecryptInit_ex(ctx, EVP_sm4_cbc(), NULL, (const unsigned char*)key, (const unsigned char*)ivec) != 1){printf("EVP_DecryptInit_ex failed.\n");return -1;}int outlen = 0;unsigned char decData[1024] = { 0 };int decDataLen = 0;int decDataLenTemp = 0;//解密操作if(EVP_DecryptUpdate(ctx, decData, &decDataLen, encData, encDataLen) != 1){printf("EVP_DecryptUpdate failed.\n");return -1;}//结束解密操作if(EVP_DecryptFinal_ex(ctx, decData + decDataLen, &decDataLenTemp) != 1){printf("EVP_DecryptFinal_ex failed.\n");return -1;}decDataLen += decDataLenTemp;decData[decDataLen] = '\0';printf("decData = %s\n", decData);EVP_CIPHER_CTX_free(ctx);	return 0;}
    

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

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

相关文章

深度学习之基于YOLOV5的口罩检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着全球公共卫生事件的频发&#xff0c;口罩成为了人们日常生活中不可或缺的一部分。在公共场所&am…

10、SpringBoot 源码分析 - 自动配置深度分析三

SpringBoot 源码分析 - 自动配置深度分析三 refresh和自动配置大致流程AutoConfigurationImportSelector的getAutoConfigurationEntry获取自动配置实体(重点)AutoConfigurationImportSelector的getCandidateConfigurations获取EnableAutoConfiguration类型的名字集合AutoConfig…

Android中JVM内存回收机制

文章目录 分代收集算法&#xff1a;新生代&#xff08;Young Generation&#xff09;老年代&#xff08;Old Generation&#xff09; 垃圾回收器&#xff1a;JVM常见三大回收算法&#xff1a;Mark-Sweep(标记清除)优点:缺点: 复制算法优点&#xff1a;缺点&#xff1a; Mark-Co…

ubuntu下交叉编译安卓FFmpeg 和 官方指导链接

将之前的编译方法在此记录 Linux系统&#xff1a;Ubuntu 18.04.6 LTS 交叉编译工具链&#xff1a;gcc-aarch64-linux-gnu gaarch64-linux-gnu ffmpeg版本&#xff1a;5.1.3 1.下载源码 ffmpeg官网&#xff1a;https://ffmpeg.org/download.html#releases 下载完成后&#x…

Edge浏览器“此页存在问题”解决思路

Edge浏览器显示“此页存在问题”解决思路 大家平时使用Edge浏览器时&#xff0c;是否和我一样会突然出现“此页存在问题”的情况&#xff1f; 经过百度查询后我找了一种情况和解决办法&#xff0c;能够大大减少这类问题的出现。出现“此页存在问题”可能是因为之前使用过软件…

每天一个数据分析题(三百四十一)

如何获取更多优质流量是电商行业中重要课题&#xff0c;下列哪些属于流量类指标 A. 平均访问深度 B. 跳失次数 C. 浏览量 D. 客单价 数据分析认证考试介绍&#xff1a;点击进入 题目来源于CDA模拟题库 点击此处获取答案

Linux基础命令[27]-gpasswd

文章目录 1. gpasswd 命令说明2. gpasswd 命令语法3. gpasswd 命令示例3.1 不加参数3.2 -a&#xff08;将用户加入组&#xff09;3.3 -d&#xff08;从组中删除用户&#xff09;3.4 -r&#xff08;删除组密码&#xff09;3.5 -M&#xff08;多个用户一起加入组&#xff09;3.6 …

React中 将UI 视为树

当 React 应用程序逐渐成形时&#xff0c;许多组件会出现嵌套。那么 React 是如何跟踪应用程序组件结构的&#xff1f; React 以及许多其他 UI 库&#xff0c;将 UI 建模为树。将应用程序视为树对于理解组件之间的关系以及调试性能和状态管理等未来将会遇到的一些概念非常有用。…

Python教程:使用Python和PyQt编写进制转换器工具

1.介绍 在现代计算中&#xff0c;进制转换是一项常见且重要的任务。为了简化这个过程&#xff0c;我们也可以利用Python和PyQt自己写一个直观且易于使用的进制转换器工具。这个工具将支持二进制、八进制、十进制和十六进制的相互转换&#xff0c;并提供良好的用户界面和交互体…

Java设计模式(23种设计模式 重点介绍一些常用的)

创建型模式&#xff0c;共五种&#xff1a;工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。结构型模式&#xff0c;共七种&#xff1a;适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。行为型模式&#xff0c;共十一种&#xff1a;…

MySQL---函数与约束

目录 一、函数 1. 字符串函数 2. 数值函数 3. 日期函数 4. 流程函数 5. 总结 二、约束 1. 概述 2. 约束演示 3. 外键约束 3.1 添加外键 3.2 删除外键 3.3 外键删除更新行为 4. 总结 一、函数 1. 字符串函数 命令如下所示&#xff1a; -- concat select concat("Hel…

苹果CMS:如何去掉首页帮助提示信息

首先我们安装好苹果CMS&#xff0c;未安装的可以参考苹果cms&#xff1a;介绍及安装 安装好之后我们需要进入模版设置&#xff0c;可能对于刚刚接触CMS框架的朋友是不清楚地址的&#xff1a; https://www.yourweb.com/admin_login.php/admin/mxpro/mxproset 其中【yourweb】…

爱设计AiPPT.cn赵充:营销工作的AI进化

爱设计&AiPPT.cn是一家 AIGC 数字科技企业&#xff0c;致力于打造「下一代个人与组织的 Ai 工作站」 。目前旗下产品包括AiPPT.cn、爱设计AIGC 内容中台、365 编辑器、爱设计在线设计工具、AiH5 等超过 10 余款应用 AI 能力的内容创作工具。日前&#xff0c;爱设计&AiP…

python的协程异步

参考资料 https://blog.csdn.net/qq_43380180/article/details/111573642?spm1001.2014.3001.5506 协程的概念 指的是在一个线程中&#xff0c;可以在某个地方挂起的特殊函数&#xff0c;并且可以重新在挂起处继续运行。协程不是进程&#xff0c;也不是线程。 进程 VS 线程…

dcache-android框架中的设计模式详解

引言&#xff1a;孤独的人喜欢深夜&#xff0c;多情的人喜欢黄昏。幸福的人喜欢阳光&#xff0c;伤心的人偏爱风雨。 众所周知&#xff0c;dcache-android是本人一行一行代码手写出来的Android数据缓存框架&#xff0c;写了好几年了&#xff0c;虽然不是每天写&#xff0c;但一…

【go从入门到精通】精通并发编程-使用扇入扇出提升多个通道之间传递数据的效率

在并发编程领域,Golang 作为一种擅长处理并发的编程语言而脱颖而出。 Go 并发模型的一个关键组件是通道,它允许 goroutine 进行通信并同步其工作。在这里,我们将探讨在 Go 中的多个通道之间传递数据的技术。当需要协调不同 goroutine 之间的工作并管理数据流时,这非常有用。…

TypeScript-类型断言

类型断言 当开发者比TS本身更清楚当前的类型是什么&#xff0c;可以使用断言(as)让类型更加精确和具体 const _link document.getElementById(link) console.log(_link.href) // 出错了&#xff0c;如下图 const _link document.getElementById(link) as HTMLAnchorElement…

【三数之和】python,排序+双指针

暴力搜索3次方的时间复杂度&#xff0c;大抵超时 遇到不会先排序 排序双指针 上题解 照做 class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:res[]nlen(nums)#排序降低复杂度nums.sort()k0#留两个位置给双指针i,jfor k in range(n-2):if nums[k]…

【再探】Java—泛型

Java 泛型本质是参数化类型&#xff0c;可以用在类、接口和方法的创建中。 1 “擦除式”泛型 Java的“擦除式”的泛型实现一直受到开发者的诟病。 “擦除式”的实现几乎只需要在Javac编译器上做出改进即可&#xff0c;不要改动字节码、虚拟机&#xff0c;也保证了以前没有使…

光伏电站在线监测智能诊断系统:开启无人值守新纪元

光伏电站在线监测智能诊断系统&#xff1a;开启无人值守新纪元 大家都知道光伏电站是通过汲取着太阳的光芒&#xff0c;为人类提供源源不断的电能源。然而&#xff0c;随着光伏电站规模的扩大和复杂性的增加&#xff0c;如何有效提高发电效率、减少人工维护成本&#xff0c;实…