openssl3.2 - exp - AES-256-GCM

文章目录

    • openssl3.2 - exp - AES-256-GCM
    • 概述
    • AES-256-GCM加密入参
    • AES-256-GCM加密出参
    • AES-256-GCM解密入参
    • AES-256-GCM解密出参
    • 笔记
    • END

openssl3.2 - exp - AES-256-GCM

概述

工程中要用到对称加密, 没得选, 要用AES256.
在openssl3.2中, AES256加解密的种类有好多种.
查了资料, 用AE-S256-GCM不错. 如果密文被修改, 就无法解密成功. 不用再另外传HASH给解密一方(让对方自己算是否密文被修改).
AES-256-GCM的明文可以为任意长度, 不需要进行填充对齐(padding).

AES-256-GCM加密入参

PT - 明文
KEY
IV
AAD - 认证数据(双方已经的确定数据), 我这里用的32字节, 等用到的时候, 再试试, 是否可以为不规则长度的数据, 是否有长度限制

AES-256-GCM加密出参

RC - 1为TRUE, 0为失败
CT - 密文
TAG - 16字节, 解密时要用

AES-256-GCM解密入参

CT - 密文
KEY
IV
AAD - 同加密时是一个东西
TAG - 加密出参返回的16个字节的TAG

AES-256-GCM解密出参

CT-PT 解密后的明文
如果密文被修改, 就不可能解密成功

笔记

/*!
* \file main.cpp
* \note openssl3.2 - exp - AES-256-GCM
* AES-256-GCM可以知道密文是否被修改, 而普通的AES-256直接无脑解密
*///! \note assert()只在debug版下生效
//! 如果是release版, 相当于没有assert()括号中的那些内容
//! 所以, 不要将逻辑代码放到断言中. 如果是要加断言, 也要判断逻辑代码执行完后的标记值.#include "my_openSSL_lib.h"
#include <openssl/crypto.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/core_names.h>#include <stdlib.h>
#include <stdio.h>
#include <assert.h>#include "CMemHookRec.h"void my_openssl_app();// ct means 密文输出
// pt means 明文
// add means 附加认证数据
bool enc_aes_256_gcm(OUT UCHAR* ct, OUT int& len_ct, UCHAR* pt, int len_pt, UCHAR* key, int len_key, UCHAR* iv, int len_iv, UCHAR* aad, int len_aad, OUT UCHAR* tag, IN int len_tag);
bool dec_aes_256_gcm(IN UCHAR* ct, IN int len_ct, OUT UCHAR* pt, OUT int& len_pt, UCHAR* key, int len_key, UCHAR* iv, int len_iv, UCHAR* aad, int len_aad, IN UCHAR* tag, IN int len_tag);int main(int argc, char** argv)
{setvbuf(stdout, NULL, _IONBF, 0); // 清掉stdout缓存, 防止调用printf时阻塞mem_hook();my_openssl_app();mem_unhook();return 0;
}char int2char(int i)
{char c_rc = '\0';i = i % 0x10;if ((i >= 0) && (i <= 9)){c_rc = '0' + i;}else if ((i >= 0x0A) && (i <= 0x0F)){c_rc = 'A' + (i - 0x0A);}else {assert(false);}return c_rc;
}// #define SIM_CT_MODIFY // 定义此宏, 模拟密文被修改后再解密的错误void my_openssl_app()
{	// 算法参数UCHAR gcm_key[32];size_t gcm_keylen = sizeof(gcm_key);UCHAR gcm_iv[32];size_t gcm_ivlen = sizeof(gcm_iv);// 附加认证数据(选择加解密双方都知道的确定数据就行)UCHAR gcm_aad[32];int gcm_addlen = sizeof(gcm_aad);int i_rc = 0;char gcm_pt[4 * 1024 - 3]; // GCM明文int i = 0;char gcm_ct[4 * 1024]; // CGM密文int len_ct = sizeof(gcm_ct);char gcm_ct_pt[4 * 1024]; // CGM密文解密后的明文int len_ct_pt = sizeof(gcm_ct_pt);// 加密时, 返回密文和TAG// 解密时, 要给加密返回的TAGUCHAR gcm_tag[16]; // 单步openssl实现, tag最多16个字节, 否则报错bool b_rc = false;do {// 准备GCM明文for (i = 0; i < sizeof(gcm_pt); i++){gcm_pt[i] = int2char(i);}// 准备gcm keyi_rc = RAND_bytes(gcm_key, sizeof(gcm_key));if (1 != i_rc){assert(false);break;}// 准备gcm ivi_rc = RAND_bytes(gcm_iv, sizeof(gcm_iv));if (1 != i_rc){assert(false);break;}// 初始化aad(实际应用中, 这个gcm_aad是双方都知道的确定数据)i_rc = RAND_bytes(gcm_aad, sizeof(gcm_aad));if (1 != i_rc){assert(false);break;}// 加解密时的入参(key, iv, aad)都是一样的// 加密后, 会返回密文和TAG, tag最多16个字节, tag解密时要用if (!enc_aes_256_gcm((UCHAR*)gcm_ct, len_ct, (UCHAR*)gcm_pt, sizeof(gcm_pt), gcm_key, sizeof(gcm_key), gcm_iv, sizeof(gcm_iv), gcm_aad, sizeof(gcm_aad), gcm_tag, sizeof(gcm_tag))){assert(false);break;}// 解密时, 要给出密文和tag, 返回解密后的明文if (!dec_aes_256_gcm((UCHAR*)gcm_ct, len_ct, (UCHAR*)gcm_ct_pt, len_ct_pt, gcm_key, sizeof(gcm_key), gcm_iv, sizeof(gcm_iv), gcm_aad, sizeof(gcm_aad), gcm_tag, sizeof(gcm_tag))){assert(false);break;}// 比较原始明文和解密后的明文是否一致if (len_ct_pt != sizeof(gcm_pt)){assert(false);break;}i_rc = memcmp(gcm_pt, gcm_ct_pt, sizeof(gcm_pt));if (0 != i_rc){assert(false);break;}#ifdef SIM_CT_MODIFY// 模拟密文被修改的情况, 这时用普通的AES256解密是验证不出来密文是否被修改(都是buffer), 而AES-256-GCM可以// 解密时, 要给出密文和tag, 返回解密后的明文gcm_ct[0] = gcm_ct[0] + 1;// 在dec_aes_256_gcm()中的 EVP_DecryptFinal_ex()处, 就执行失败if (!dec_aes_256_gcm((UCHAR*)gcm_ct, len_ct, (UCHAR*)gcm_ct_pt, len_ct_pt, gcm_key, sizeof(gcm_key), gcm_iv, sizeof(gcm_iv), gcm_aad, sizeof(gcm_aad), gcm_tag, sizeof(gcm_tag))){assert(false);break;}// 比较原始明文和解密后的明文是否一致if (len_ct_pt != sizeof(gcm_pt)){assert(false);break;}i_rc = memcmp(gcm_pt, gcm_ct_pt, sizeof(gcm_pt));if (0 != i_rc){assert(false);break;}
#endif // #ifdef SIM_CT_MODIFYb_rc = true;} while (false);assert(true == b_rc);
}bool enc_aes_256_gcm(OUT UCHAR* ct, OUT int& len_ct, UCHAR* pt, int len_pt, UCHAR* key, int len_key, UCHAR* iv, int len_iv, UCHAR* aad, int len_aad, OUT UCHAR* tag, IN int len_tag)
{// openssl库上下文和属性OSSL_LIB_CTX* libctx = NULL;const char* propq = NULL;// 算法上下文和算法指针EVP_CIPHER_CTX* ctx = NULL;EVP_CIPHER* cipher = NULL;OSSL_PARAM gcm_params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };size_t gcm_ivlen = 0;bool b_rc = false;int i_rc = 0;int tmplen = 0;do {if ((NULL == ct) || (len_ct <= 0) || (NULL == pt) || (len_pt <= 0) || (len_ct < len_pt)){assert(false);break;}if ((NULL == key) || (len_key <= 0) || (NULL == iv) || (len_iv <= 0)){assert(false);break;}ctx = EVP_CIPHER_CTX_new();assert(NULL != ctx);if (NULL == ctx){break;}cipher = EVP_CIPHER_fetch(libctx, "AES-256-GCM", propq);assert(NULL != cipher);if (NULL == cipher){break;}gcm_ivlen = len_iv;gcm_params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, &gcm_ivlen);i_rc = EVP_EncryptInit_ex2(ctx, cipher, key, iv, gcm_params);assert(1 == i_rc);if (1 != i_rc){break;}// set aad to ctxtmplen = 0;i_rc = EVP_EncryptUpdate(ctx, NULL, &tmplen, aad, len_aad);assert(1 == i_rc);if (1 != i_rc){break;}assert(tmplen == len_aad);if (tmplen != len_aad){break;}assert(len_pt <= len_ct);if (len_pt > len_ct){break;}i_rc = EVP_EncryptUpdate(ctx, ct, &len_ct, pt, len_pt);assert(1 == i_rc);if (1 != i_rc){break;}assert(len_ct == len_pt);if (len_ct != len_pt){break;}// get no output's enc texti_rc = EVP_EncryptFinal_ex(ctx, ct + len_ct, &tmplen);assert(1 == i_rc);if (tmplen > 0){len_ct += tmplen;}/* Get tag */// aes-256-gcm加密完, 除了输出密文, 还输出tag.// 输出的密文和tag给解密用gcm_params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, tag, len_tag);i_rc = EVP_CIPHER_CTX_get_params(ctx, gcm_params);assert(1 == i_rc);if (1 != i_rc){break;}b_rc = true;} while (false);if (NULL != cipher){EVP_CIPHER_free(cipher);}if (NULL != ctx){EVP_CIPHER_CTX_free(ctx);}return b_rc;
}bool dec_aes_256_gcm(IN UCHAR* ct, IN int len_ct, OUT UCHAR* pt, OUT int& len_pt, UCHAR* key, int len_key, UCHAR* iv, int len_iv, UCHAR* aad, int len_aad, IN UCHAR* tag, IN int len_tag)
{// openssl库上下文和属性OSSL_LIB_CTX* libctx = NULL;const char* propq = NULL;// 算法上下文和算法指针EVP_CIPHER_CTX* ctx = NULL;EVP_CIPHER* cipher = NULL;OSSL_PARAM gcm_params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };size_t gcm_ivlen = 0;bool b_rc = false;int i_rc = 0;int tmplen = 0;do {if ((NULL == ct) || (len_ct <= 0) || (NULL == pt) || (len_pt <= 0) || (len_ct > len_pt)){assert(false);break;}if ((NULL == key) || (len_key <= 0) || (NULL == iv) || (len_iv <= 0)){assert(false);break;}ctx = EVP_CIPHER_CTX_new();if (NULL == ctx){assert(false);break;}cipher = EVP_CIPHER_fetch(libctx, "AES-256-GCM", propq);if (NULL == cipher){assert(false);break;}gcm_ivlen = len_iv;gcm_params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, &gcm_ivlen);i_rc = EVP_DecryptInit_ex2(ctx, cipher, key, iv, gcm_params);if (1 != i_rc){assert(false);break;}// set aad to ctxtmplen = 0;i_rc = EVP_DecryptUpdate(ctx, NULL, &tmplen, aad, len_aad);if ((1 != i_rc) || (tmplen != len_aad)){assert(false);break;}i_rc = EVP_DecryptUpdate(ctx, pt, &len_pt, ct, len_ct);if (1 != i_rc){assert(false);break;}/* Set expected tag value. */gcm_params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, (void*)tag, len_tag);i_rc = EVP_CIPHER_CTX_set_params(ctx, gcm_params);if (1 != i_rc){assert(false);break;}/* Finalise: note get no output for GCM */i_rc = EVP_DecryptFinal_ex(ctx, pt + len_pt, &tmplen);if (1 != i_rc){// 如果密文被修改, 到这里就有断言assert(false);break;}if (tmplen > 0){len_pt += tmplen;}b_rc = true;} while (false);if (NULL != cipher){EVP_CIPHER_free(cipher);}if (NULL != ctx){EVP_CIPHER_CTX_free(ctx);}return b_rc;
}

END

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

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

相关文章

FreeRTOS操作系统学习——任务管理

任务概念 在FreeRTOS中&#xff0c;一个任务相当于一个线程&#xff0c;可以有很多的任务&#xff0c;每个人任务可以设置不同的优先级。相同优先级的任务轮流使用CPU&#xff0c;高优先级的任务可以一直使用CPU&#xff0c;直到主动放弃&#xff0c;低级的任务才有被执行的机…

深入解析Java 8中的Optional类和Stream API

摘要&#xff1a; Java 8作为Java语言的一个重要版本&#xff0c;引入了许多新特性和改进。其中&#xff0c;Optional类和Stream API是两个非常受欢迎的特性&#xff0c;它们为Java带来了函数式编程的能力。本文将深入探讨Java 8中的Optional类和Stream API&#xff0c;通过两个…

SpringBoot集成数据库界的版本控制工具flyway

Flyway 就是一款数据库界的版本控制工具&#xff0c;它可以记录数据库的变化记录。统一管理所有的 SQL 脚本变更&#xff0c;在所有环境自动同步数据库&#xff0c;而无需人为手工控制&#xff0c;再也不用担心因数据库不同步而导致的各种环境问题。 MySQL环境准备 version: 3…

国产蓝鹏测控测径仪如何?

随着国力增强&#xff0c;中国制造品质提升&#xff0c;不仅仅是国外更多人认可&#xff0c;国内对国产制品也接受良好&#xff0c;测径仪这种智能测量设备&#xff0c;很多国内外厂家也在用国产设备。 测径仪厂家 蓝鹏测控作为智能几何尺寸测量仪生产厂家&#xff0c;已有10多…

MMdetection3D-v1.1.0rc5安装教程

文章目录 前言安装步骤1.创建环境并运行2.安装torch3.安装mmcv-full3.安装mmcls、mmsegmentation、mmdet4.源码安装mmdet3d5.补充测试效果 pip list汇总 前言 相信大家在开始学习mmdet3d时都会碰到环境安装失败的问题&#xff0c;特别是安装低版本mmdet3d时&#xff0c;由于官…

Spring框架Bean对象的五个作用域

一、前言&#xff1a;Bean对象简介 在Spring项目中&#xff0c;那些由Spring IoC容器所管理的对象&#xff0c;称为bean。简单地讲&#xff0c;bean就是由Spring容器初始化、装配及管理的对象&#xff0c;除此之外&#xff0c;bean就与应用程序中的其他对象没有什么区别了。 而…

C++初阶:初识C++

目录 1. 前言&#xff1a;C 与 C语言2. C对于C语言语法的完善与补充2.1 命名冲突与命名空间2.1.1 命名空间的定义2.1.2 调用方式 2.3 补充&#xff1a;流的概念2.4 缺省参数2.4.1 缺省参数的使用 2.5 函数重载2.5.1 什么是函数重载2.5.2 函数重载的使用2.5.3 特殊情况&#xff…

SpringBoot集成JSP和war包部署到Tomcat

SpringBoot集成JSP 加依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot…

MedSAM 项目排坑记录

MedSAM 项目排坑记录 任务排坑过程配置python环境测试构建docker模型训练数据预处理 单GPU训练最后推理 任务 做一个课程大作业&#xff0c;需要进行CVPR2024年医疗影像分割赛题的打榜&#xff08;CVPR 2024: SEGMENT ANYTHING IN MEDICAL IMAGES ON LAPTOP&#xff09;。看到…

SQL练习--day01

1、需求&#xff1a;编写一条sql&#xff0c;满足以下条件&#xff0c;无论person是否有地址消息&#xff0c;都需要基于上述两表提供的person的一下信息&#xff1a;firstname 、lastname、city、state 表1&#xff1a;person列名 类型 personid int&#xf…

Nginx限流限速艺术揭秘:从原理到实战,轻松实现服务流量控制

在高并发的互联网时代&#xff0c;服务器承载的压力日益增大。为了保证服务稳定性和用户体验&#xff0c;对系统进行合理的流量控制至关重要。本文将深入浅出地解析Nginx的限流与限速机制&#xff0c;并指导您如何通过配置Nginx实现精准、高效的流量控制。 一、Nginx限流限速原…

nginx配置https访问

1、先去申请ssl证书&#xff0c;这里就不多说了 2、nginx配置https 修改nginx配置文件&#xff0c;开启https server {listen 80;server_name 127.0.0.1;#将请求转成https#早期写法rewrite ^(.*)$ https://$host$1;#最新写法return 301 https://$server_name$request_u…

docker离线搭建仓库

要在Docker中搭建本地仓库&#xff0c;可以按照以下步骤进行操作&#xff1a; 首先安装 Docker。根据不同的操作系统选择合适的版本并完成安装过程。打开命令行工具&#xff08;如Terminal或PowerShell&#xff09;&#xff0c;运行以下命令来创建一个新的容器并将其设置为本地…

vulhub中ThinkPHP 多语言本地文件包含漏洞复现

ThinkPHP是一个在中国使用较多的PHP框架。在其6.0.13版本及以前&#xff0c;存在一处本地文件包含漏洞。当多语言特性被开启时&#xff0c;攻击者可以使用lang参数来包含任意PHP文件。 虽然只能包含本地PHP文件&#xff0c;但在开启了register_argc_argv且安装了pcel/pear的环…

基础 | 安全 - [加密]

INDEX 1 加密类型1.1 对称加密1.2 非对称加密1.3 混合加密1.4 摘要算法1.5 数据证书 1 加密类型 1.1 对称加密 即加密解密的秘钥是一样的&#xff0c;报文用什么加密就需要用什么解密 优点&#xff1a;快&#xff0c;模型简单 缺点&#xff1a;安全性查&#xff0c;秘钥需要通…

如何在Win系统本地部署Jupyter Notbook交互笔记并结合内网穿透实现公网远程使用

文章目录 1.前言2.Jupyter Notebook的安装2.1 Jupyter Notebook下载安装2.2 Jupyter Notebook的配置2.3 Cpolar下载安装 3.Cpolar端口设置3.1 Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 在数据分析工作中&#xff0c;使用最多的无疑就是各种函数、图表、…

2024第二届语言,教育与艺术鉴赏国际会议(ICLEAA 2024)

2024第二届语言&#xff0c;教育与艺术鉴赏国际会议&#xff08;ICLEAA 2024&#xff09; 一、【会议简介】 我们非常荣幸地邀请您参加2024第二届语言&#xff0c;教育与艺术鉴赏国际会议&#xff08;ICLEAA 2024&#xff09;&#xff0c;该会议将在美丽的苏州举行。 ICLEAA …

美团面试拷打:Redis 缓存穿透、缓存击穿、缓存雪崩区别和解决方案

目录&#xff1a; 缓存穿透 什么是缓存穿透&#xff1f; 缓存穿透说简单点就是大量请求的 key 是不合理的&#xff0c;根本不存在于缓存中&#xff0c;也不存在于数据库中 。这就导致这些请求直接到了数据库上&#xff0c;根本没有经过缓存这一层&#xff0c;对数据库造成了巨…

Linux centos7新增组和用户

Linux centos7命令 1、Linux centos7新增组和用户 #新增用户组 $groupadd cg #给组新增用户 useradd -g cg cg #修改用户密码 echo "lianshi" | passwd --stdin cg 2、远程拷贝scp scp -r root10.1.1.76:/data/release/xxx/xxx-20240204174841/xxx-202402041…

如何在Win系统部署Tomcat服务并实现远程访问内网站点

文章目录 前言1.本地Tomcat网页搭建1.1 Tomcat安装1.2 配置环境变量1.3 环境配置1.4 Tomcat运行测试1.5 Cpolar安装和注册 2.本地网页发布2.1.Cpolar云端设置2.2 Cpolar本地设置 3.公网访问测试4.结语 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的人工智能学…