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

相关文章

java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)

《java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)》:本文主要介绍java中pdf模版填充表单踩坑的相关资料,OpenPDF、iText、PDFBox是三... 目录准备Pdf模版方法1:itextpdf7填充表单(1)加入依赖(2)代码(3)遇到的问题方法2:pd

解密SQL查询语句执行的过程

《解密SQL查询语句执行的过程》文章讲解了SQL语句的执行流程,涵盖解析、优化、执行三个核心阶段,并介绍执行计划查看方法EXPLAIN,同时提出性能优化技巧如合理使用索引、避免SELECT*、JOIN... 目录1. SQL语句的基本结构2. SQL语句的执行过程3. SQL语句的执行计划4. 常见的性能优

一文解密Python进行监控进程的黑科技

《一文解密Python进行监控进程的黑科技》在计算机系统管理和应用性能优化中,监控进程的CPU、内存和IO使用率是非常重要的任务,下面我们就来讲讲如何Python写一个简单使用的监控进程的工具吧... 目录准备工作监控CPU使用率监控内存使用率监控IO使用率小工具代码整合在计算机系统管理和应用性能优化中,监

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文

在Spring Boot中集成RabbitMQ的实战记录

《在SpringBoot中集成RabbitMQ的实战记录》本文介绍SpringBoot集成RabbitMQ的步骤,涵盖配置连接、消息发送与接收,并对比两种定义Exchange与队列的方式:手动声明(... 目录前言准备工作1. 安装 RabbitMQ2. 消息发送者(Producer)配置1. 创建 Spr

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项