EVP AES_CBC加密解密记录

2024-03-01 17:18
文章标签 aes 解密 加密 记录 evp cbc

本文主要是介绍EVP AES_CBC加密解密记录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近学习了openssl中AES有关加密解密的接口,以下内容为测试代码,需要注意使用EVP函数接口实现AES_CBC时需注意末尾字符的填充处理,我使用的算法为“EVP_aes_128_cbc”,需要注意的是分组加密中最小组为16字节,加密操作中使用的缓冲区需比源数据多16个字节,原因是若分组后最后一组数据不够16个字节,则按照填充规则填满至16字节,若分组后正好是16的整数倍,最后需再加一个分组,并将16个字节按照规则填充。

#include<iostream>
#include<stdio.h>
#include<openssl/evp.h>


#define MSG_LEN 16
#define IV_LEN 16
#define DECRY 0
#define ENCRY 1

typedef enum{
    AES_CBC,
    AES_EBC  
}EVP_ALGORITHM;


void my_evp_init()
{
//如果不经过初始化就调用了加密或摘要相关的EVP接口,则会返回错误。

//OpenSSL中所有的对称和摘要算法都需要进行全局初始化,方法如下:
    OpenSSL_add_all_algorithms();
//当然也可以只载入加密算法或摘要算法

//  OpenSSL_add_all_digest();
//  OpenSSL_add_all_cipher();

    return;
}

//对称算法
/*
*@ciphername 算法名称,通过此名称找到EVP_CIPHER结构
*@dir 加密解密标志,0为解密,非0为加密
*@aKey 对称算法秘钥
*@iVec IV向量
*
*/

static int OpenSSL_Cipher(int ciphername, int dir, 
              const unsigned char *aKey, const unsigned char *iVec,
              const unsigned char *in, int inlen,
              unsigned char *out, int *poutlen)
{
    int rv = 0, tmplen = 0;

    const EVP_CIPHER *cipher = NULL;
    EVP_CIPHER_CTX ctx;

    /* 初始化加密调用的上下文 */   
    EVP_CIPHER_CTX_init(&ctx);

    /* 根据名称(如des-cbc,或rc4)获取CIPHER对象,OpenSSL支持的算法名称可以用openssl enc -h命令列出 */ 
    #if 0
    cipher = EVP_get_cipherbyname(ciphername);
    if (NULL == cipher) {
        fprintf( stderr, "OpenSSL_Cipher: Cipher for %s is NULL\n", ciphername );

        rv = -1;
        goto err;
    }
    #endif
    printf("ciphername is %d\n",ciphername);
    printf("AES_CBC is %d\n",AES_CBC);
    switch(ciphername)
    {
      case AES_CBC:
        cipher = EVP_aes_128_cbc();
        break;    
      default:
        printf("no switch EVP_CIPHER");
        return -9;
    }
    /**
     * 初始化算法:设置对称算法的密钥,IV,以及加解密标志位dir
     * 如果使用Engine,此时会调用其实现的EVP_CIPHER->init回调函数
     */
    if (!EVP_CipherInit_ex(&ctx, cipher, NULL, aKey, iVec, dir)) {

        fprintf( stderr, "OpenSSL_Cipher: EVP_CipherInit failed\n");

        rv = -2;
        goto err;
    }

    /**
     * 对数据进行加/解密运算(如果使用Engine,此时会调用其实现的EVP_CIPHER->do_cipher回调函数)
     * 对于连续数据流,CipherUpdate一般会被调用多次
     */
    if (!EVP_CipherUpdate(&ctx, out, poutlen, in, inlen)) {
        fprintf( stderr, "OpenSSL_Cipher: EVP_CipherInit failed\n");

        rv = -3;
        goto err;
    }

    /**
     * 输出最后一块数据结果(块加密时,数据将被padding到block长度的整数倍,因此会产生额外的最后一段数据)
     * 注意:如果使用Engine,此时会触发其实现的EVP_CIPHER->do_cipher,而不是EVP_CIPHER->cleanup
     *       这点上与EVP_DigestFinal/EVP_SignFinal/EVP_VerifyFinal是完全不同的
     */ 
    if (!EVP_CipherFinal(&ctx, out + *poutlen, &tmplen)) {
        fprintf( stderr, "OpenSSL_Cipher: EVP_CipherInit failed\n");

        rv = -4;
        goto err;
    }

    *poutlen += tmplen;

err:    
    /* 释放上下文(如果使用Engine,此时会调用其实现的EVP_CIPHER->cleanup回调函数) */    
    EVP_CIPHER_CTX_cleanup(&ctx);

    return rv;
}


void my_evp_free()
{
//与OpenSSl_add_all_algorithms正好相反
    EVP_cleanup();
    return;
}


int main(int argc,char *argv[])
{
    EVP_ALGORITHM chname;
    
    printf("chname = %d\n",chname);
    chname = AES_CBC;
    printf("chname = %d\n",chname);
    #if 1
    int i = 0;
    int detct_len = 0;
    int source_len = 0;
    unsigned char source[4*MSG_LEN] = {0};
    unsigned char detct[4*MSG_LEN] = {0};
    
    my_evp_init();
    
    FILE * fre = fopen(argv[1],"rb");
    size_t fre_len = 0;
    FILE * fwr = fopen(argv[2],"wb");
    size_t fwr_len = 0;

    unsigned char key[16] = {0};
    unsigned char iv[16] = {0};

    for(i = 0;i<16;i++)
        key[i] = 32 + i;
    
    while(!feof(fre))
    {
        printf("chname = %d\n",chname);
        fre_len = fread(source,sizeof(char),2*MSG_LEN,fre);
        OpenSSL_Cipher(chname, ENCRY,key,iv,source,fre_len,detct,&detct_len);
        printf("detct_len = %d\n",detct_len);
        
        memset(source,0,sizeof(source));
        OpenSSL_Cipher(chname, DECRY,key,iv,detct,detct_len,source,&source_len);    
        printf("source_len = %d\n",source_len);
        fwr_len = fwrite(source,sizeof(char),source_len,fwr);
        
    } 

    fclose(fre);
    fclose(fwr);
    

    my_evp_free();
    #endif
    return 0;
}
 

这篇关于EVP AES_CBC加密解密记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/763213

相关文章

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

perl的学习记录——仿真regression

1 记录的背景 之前只知道有这个强大语言的存在,但一直侥幸自己应该不会用到它,所以一直没有开始学习。然而人生这么长,怎就确定自己不会用到呢? 这次要搭建一个可以自动跑完所有case并且打印每个case的pass信息到指定的文件中。从而减轻手动跑仿真,手动查看log信息的重复无效低质量的操作。下面简单记录下自己的思路并贴出自己的代码,方便自己以后使用和修正。 2 思路整理 作为一个IC d

3.比 HTTP 更安全的 HTTPS(工作原理理解、非对称加密理解、证书理解)

所谓的协议 协议只是一种规则,你不按规则来就无法和目标方进行你的工作 协议说白了只是人定的规则,任何人都可以定协议 我们不需要太了解细节,这些制定和完善协议的人去做的,我们只需要知道协议的一个大概 HTTPS 协议 1、概述 HTTPS(Hypertext Transfer Protocol Secure)是一种安全的超文本传输协议,主要用于在客户端和服务器之间安全地传输数据

SSM项目使用AOP技术进行日志记录

本步骤只记录完成切面所需的必要代码 本人开发中遇到的问题: 切面一直切不进去,最后发现需要在springMVC的核心配置文件中中开启注解驱动才可以,只在spring的核心配置文件中开启是不会在web项目中生效的。 之后按照下面的代码进行配置,然后前端在访问controller层中的路径时即可观察到日志已经被正常记录到数据库,代码中有部分注释,看不懂的可以参照注释。接下来进入正题 1、导入m

ja-netfilter的前世今生和非对称加密的欺骗原理

文章目录 ja-netfilter起源官网插件插件配置文件插件的综合应用更多用法 非对称加密欺骗原理非对称加密和数字证书激活过程和欺骗手段分析代码示例第一步:生成自签名证书脚本第二步:使用自签名证书对产品激活信息进行签名 样例数据样例激活码(注:用于代码演示,直接粘贴到JetBrains 家 IDE 中无法完成激活!不用试,肯定提示无效,无法激活!!)样例power.conf(配合ja-ne

flume系列之:记录一次flume agent进程被异常oom kill -9的原因定位

flume系列之:记录一次flume agent进程被异常oom kill -9的原因定位 一、背景二、定位问题三、解决方法 一、背景 flume系列之:定位flume没有关闭某个时间点生成的tmp文件的原因,并制定解决方案在博主上面这篇文章的基础上,在机器内存、cpu资源、flume agent资源都足够的情况下,flume agent又出现了tmp文件无法关闭的情况 二、

Linux常用工具与命令日常记录(长期更新)

Linux常用工具与命令日常记录(长期更新) 目录 1.本地复制到远程2.Linux压缩拆包与解压3.生成随机密码4.ubuntu默认Python版本设置5.计算当前文件夹中文件数量6.windows中编写shell脚本,在Linux运行出错7.history 历史命令显示时间用户8.Ubuntu18.04设置源、网卡9.Ubuntu18.04设置网卡10.Ubuntu:自定义开