当前位置: 首页 > 编程日记 > 正文

对称加密算法AES之GCM模式简介及在OpenSSL中使用举例

AES(Advanced Encryption Standard)即高级加密标准,由美国国家标准和技术协会(NIST)于2000年公布,它是一种对称加密算法。关于AES的更多介绍可以参考:https://blog.csdn.net/fengbingchun/article/details/100139524

AES的GCM(Galois/Counter Mode)模式本质上是AES的CTR模式(计数器模式)加上GMAC(Galois Message Authentication Code, 伽罗华消息认证码)进行哈希计算的一种组合模式。GCM可以提供对消息的加密和完整性校验,另外,它还可以提供附加消息的完整性校验。

OpenSSL中的EVP接口支持执行经过身份验证的加密和解密的功能,以及将未加密的关联数据附加到消息的选项。这种带有关联数据的身份验证加密(AEAD, Authenticated-Encryption with Associated-Data)方案通过对数据进行加密来提供机密性,并通过在加密数据上创建MAC标签来提供真实性保证。

Key:对称密钥,它的长度可以为128、192、256bits,用来加密明文的密码。

IV(Initialisation Vector):初始向量,它的选取必须随机。通常以明文的形式和密文一起传送。它的作用和MD5的”加盐”有些类似,目的是防止同样的明文块,始终加密成同样的密文块。

AAD(Additional Authenticated Data):附加身份验证数据。AAD数据不需要加密,通常以明文形式与密文一起传递给接收者。

Mac tag(MAC标签):将确保数据在传输和存储过程中不会被意外更改或恶意篡改。该标签随后在解密操作期间使用,以确保密文和AAD未被篡改。在加密时,Mac tag由明文、密钥Key、IV、AAD共同产生。

以下为测试代码:

namespace {static const unsigned char gcm_key[] = { // 32 bytes, Key0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66,0x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f
};static const unsigned char gcm_iv[] = { // 12 bytes, IV(Initialisation Vector)0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84
};// Additional Authenticated Data(AAD): it is not encrypted, and is typically passed to the recipient in plaintext along with the ciphertext
static const unsigned char gcm_aad[] = { // 16 bytes0x4d, 0x23, 0xc3, 0xce, 0xc3, 0x34, 0xb4, 0x9b, 0xdb, 0x37, 0x0c, 0x43,0x7f, 0xec, 0x78, 0xde
};std::unique_ptr<unsigned char[]> aes_gcm_encrypt(const char* plaintext, int& length, unsigned char* tag)
{EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();// Set cipher type and modeEVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr);// Set IV length if default 96 bits is not appropriateEVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(gcm_iv), nullptr);// Initialise key and IVEVP_EncryptInit_ex(ctx, nullptr, nullptr, gcm_key, gcm_iv);// Zero or more calls to specify any AADint outlen;EVP_EncryptUpdate(ctx, nullptr, &outlen, gcm_aad, sizeof(gcm_aad));unsigned char outbuf[1024];// Encrypt plaintextEVP_EncryptUpdate(ctx, outbuf, &outlen, (const unsigned char*)plaintext, strlen(plaintext));length = outlen;std::unique_ptr<unsigned char[]> ciphertext(new unsigned char[length]);memcpy(ciphertext.get(), outbuf, length);// Finalise: note get no output for GCMEVP_EncryptFinal_ex(ctx, outbuf, &outlen);// Get tagEVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outbuf);memcpy(tag, outbuf, 16);// Clean upEVP_CIPHER_CTX_free(ctx);return ciphertext;
}std::unique_ptr<unsigned char[]> aes_gcm_decrypt(const unsigned char* ciphertext, int& length, const unsigned char* tag)
{EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();// Select cipherEVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr);// Set IV length, omit for 96 bitsEVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(gcm_iv), nullptr);// Specify key and IVEVP_DecryptInit_ex(ctx, nullptr, nullptr, gcm_key, gcm_iv);int outlen;// Zero or more calls to specify any AADEVP_DecryptUpdate(ctx, nullptr, &outlen, gcm_aad, sizeof(gcm_aad));unsigned char outbuf[1024];// Decrypt plaintextEVP_DecryptUpdate(ctx, outbuf, &outlen, ciphertext, length);// Output decrypted blocklength = outlen;std::unique_ptr<unsigned char[]> plaintext(new unsigned char[length]);memcpy(plaintext.get(), outbuf, length);// Set expected tag valueEVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (void*)tag);// Finalise: note get no output for GCMint rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen);// Print out return value. If this is not successful authentication failed and plaintext is not trustworthy.fprintf(stdout, "Tag Verify %s\n", rv > 0 ? "Successful!" : "Failed!");EVP_CIPHER_CTX_free(ctx);return plaintext;
}} // namespaceint test_openssl_aes_gcm()
{/* reference:https://github.com/openssl/openssl/blob/master/demos/evp/aesgcm.chttps://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption*/fprintf(stdout, "Start AES GCM 256 Encrypt:\n");const char* plaintext = "1234567890ABCDEFG!@#$%^&*()_+[]{};':,.<>/?|";fprintf(stdout, "src plaintext: %s, length: %d\n", plaintext, strlen(plaintext));int length = 0;std::unique_ptr<unsigned char[]> tag(new unsigned char[16]);std::unique_ptr<unsigned char[]> ciphertext = aes_gcm_encrypt(plaintext, length, tag.get());fprintf(stdout, "length: %d, ciphertext: ", length);for (int i = 0; i < length; ++i)fprintf(stdout, "%02x ", ciphertext.get()[i]);fprintf(stdout, "\nTag: ");for (int i = 0; i < 16; ++i)fprintf(stdout, "%02x ", tag.get()[i]);fprintf(stdout, "\n");fprintf(stdout, "\nStart AES GCM 256 Decrypt:\n");std::unique_ptr<unsigned char[]> result = aes_gcm_decrypt(ciphertext.get(), length, tag.get());fprintf(stdout, "length: %d, decrypted plaintext: ", length);for (int i = 0; i < length; ++i)fprintf(stdout, "%c", result.get()[i]);fprintf(stdout, "\n");if (strncmp(plaintext, (const char*)result.get(), length) == 0) {fprintf(stdout, "decrypt success\n");return 0;} else {fprintf(stderr, "decrypt fail\n");return -1;}
}

在Windows上执行结果如下:

以上是在OpenSSL较老的版本1.0.1g上执行的,在最新版1.1.1g上以上代码也同样可以执行。

在Windows上编译1.1.1g版本源码执行命令如下:no-asm选项为不开启汇编模式,编译release则将debug-VC-WIN64A改为VC-WIN64即可。

perl Configure debug-VC-WIN64A no-asm --prefix=D:\DownLoad\openssl\win64_debug
nmake
nmake install

在Linux上编译1.1.1g版本源码执行命令如下:

./config --prefix=/home/sensetime/Downloads/openssl/install
make
make insall

在1.1.1g源码的demos/evp目录下给出了gcm的示例aesgcm.c,这里将以上测试代码新加为aesgcm2.cpp,编译脚本如下:

#! /bin/bashg++ -o test_aesgcm aesgcm.c -L ../../ -lcrypto -lssl -I../../include
g++ -o test_aesgcm2 aesgcm2.cpp -std=c++11 -L ../../ -lcrypto -lssl -I../../includeg++ -o test_aesccm aesccm.c -L ../../ -lcrypto -lssl -I../../include

执行结果如下:注意如果在Windows上执行aesgcm2.cpp,需要额外的 #include <openssl/applink.c> 

GitHub:https://github.com//fengbingchun/OpenSSL_Test

相关文章:

iOS UITextField清空按钮

extField.clearButtonModeUITextFieldViewModeWhileEditing; 就可以了&#xff0c;表明编辑输入框的时候启动一键清空按钮。另外&#xff0c;clearButtonMode还有三个属性&#xff1a; UITextFieldViewModeNever, 清空按钮永不出现 UITextFieldViewModeUnlessEditing, 不编…

腾讯“疯狂”开源

作者 | 马超责编 | 胡巍巍出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;近日&#xff0c;腾讯自研的万亿级分布式消息中间件TubeMQ正式开源&#xff0c;并捐赠给Apache基金会&#xff0c;成为基金会官方认可的Incubator项目。我们知道与TubeMQ功能类似的kafka是领…

[Android]开发摇一摇分歧表决器过程

心血来潮&#xff0c;走进Android&#xff0c;准备开发一个摇一摇分歧表决器&#xff08;PS&#xff1a;这个想法源自去年看的一个都市剧《约会专家》中主人公杭杭开发的分歧表决器APP&#xff09;。简述&#xff1a;摇一摇分歧表决器是一款Android App&#xff0c;通过将传统的…

C和C++安全编码笔记:整数安全

5.1 整数安全导论&#xff1a;整数由包括0的自然数(0, 1, 2, 3, …)和非零自然数的负数(-1, -2, -3, …)构成。 5.2 整数数据类型&#xff1a;整数类型提供了整数数学集合的一个有限子集的模型。一个具有整数类型的对象的值是附着在这个对象上的数学值。一个具有整数类型的对象…

8.3折特惠票仅剩3天!「2019 嵌入式智能国际大会」全日程大公开!

8.3折特惠票仅剩3天立即抢购&#xff1a;https://t.csdnimg.cn/otBk还有5天&#xff0c;大伙期待的「2019嵌入式智能国际大会」正式开幕了&#xff01;2019年12月6日-7日&#xff0c;我们在深圳市人才研修院见&#xff01;大会以“万物互联泛在智能”为主题&#xff0c;邀请30位…

iOS点击空白收回键盘

//点击空白收回键盘 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; }

第一个net-mvc程序

结构 视图层 <% Page Language"C#" Inherits"System.Web.Mvc.ViewPage<dynamic>" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">…

iOS 储存用户信息设置封装 直接调用即可(部分是代码片段)

、、、、、、、、、、、、、、、、、、首先 定义 UserInfo #import <Foundation/Foundation.h> interface UserInfo : NSObject //用户id property (nonatomic, strong) NSString *userID; //用户名 property (nonatomic, strong) NSString *userName; //密码 propert…

ASN.1简介及OpenSSL中ASN.1接口使用举例

ASN.1(Abstract Syntax Notation One)是一套标准&#xff0c;是描述数据的表示、编码传输、解码的灵活的记法。它提供了一套正式、无歧义和精确的规则以描述独立于特定计算机硬件的对象结构。OpenSSL的编码方法就是基于该标准。ASN.1是一种结构化的数字对象描述语言&#xff0c…

谁是当今最顶级的技术?SQL、Java、Python、C++ 皆上榜!

【12月公开课预告】&#xff0c;入群直接获取报名地址12月11日晚8点直播主题&#xff1a;人工智能消化道病理辅助诊断平台——从方法到落地12月12日晚8点直播&#xff1a;利用容器技术打造AI公司技术中台12月17日晚8点直播主题&#xff1a;可重构计算&#xff1a;能效比、通用性…

将表里的数据批量生成INSERT语句的存储过程 增强版

原文:将表里的数据批量生成INSERT语句的存储过程 增强版将表里的数据批量生成INSERT语句的存储过程 增强版 有时候&#xff0c;我们需要将某个表里的数据全部或者根据查询条件导出来&#xff0c;迁移到另一个相同结构的库中 目前SQL Server里面是没有相关的工具根据查询条件来生…

通过OpenSSL的接口实现Base64编解码

对openssl genrsa产生的rsa私钥pem文件&#xff0c;使用普通的base64解码会有问题&#xff0c;如使用https://blog.csdn.net/fengbingchun/article/details/85218653 中介绍的方法&#xff0c;一是有可能不能从返回的结果中直接使用strlen来获得最终字符的大小&#xff0c;因为…

激辩:机器究竟能否理解常识?

【12月公开课预告】&#xff0c;入群直接获取报名地址12月11日晚8点直播主题&#xff1a;人工智能消化道病理辅助诊断平台——从方法到落地12月12日晚8点直播&#xff1a;利用容器技术打造AI公司技术中台12月17日晚8点直播主题&#xff1a;可重构计算&#xff1a;能效比、通用性…

Mac OS X 下Node.js开发环境的搭建

1.安装Xcode2.安装Homebrew 谷歌搜索Homebrew 复制命令行 打开终端 粘贴命令行 点击回车 安装 输入密码等2.安装Nodejs利用Homebrew安装nodejs打开终端 输入 &#xff1a;brew install nodejs 回车查询nodejs版本&#xff1a;node --version3.安装文档数据库 MongoDB打开终…

.NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper

.NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper 參考演示样例代码&#xff0c;例如以下所看到的&#xff1a; /// <summary>/// MySql 数据库操作类/// </summary>public class MySqlHelper{/// <summary>/// MysqlConnection/// </summ…

Instagram个性化推荐工程中三个关键技术是什么?

作者 | Ivan Medvedev&#xff0c;Haotian Wu&#xff0c;Taylor Gordon译者 | 陆离编辑 | Jane出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09; 【导语】近期&#xff0c;Facebook 在博客上分享了第一篇详细介绍 Explore 系统关键技术&#xff0c;以及 I…

iOS UIbutton 点击无反应的几种情况

1、UIButton不能点击情况的第一种是&#xff0c;你将button添加到一个不能响应点击事件的View里。如你将button添加到UIImageView中&#xff0c;解决办法只需将UIImageView的 userInteractionEnabled设为YES即可。 例如&#xff1a; self.headImgV [[UIImageView alloc] ini…

C和C++安全编码笔记:格式化输出

C标准中定义了一些可以接受可变数量参数的格式化输出参数&#xff0c;参数中包括一个格式字符串。printf()和sprintf()都是格式化输出函数的例子。格式化输出函数是由一个格式字符串和可变数目的参数构成的。在效果上&#xff0c;格式化字符串提供了一组可以由格式化输出函数解…

谈谈UI架构设计的演化

谈谈UI架构设计的演化 经典MVC 在1979年&#xff0c;经典MVC模式被提出。 在当时&#xff0c;人们一直试图将纯粹描述思维中的对象与跟计算机环境打交道的代码隔离开来&#xff0c;而Trygve Reenskaug在跟一些人的讨论中&#xff0c;逐渐剥离出一系列的概念&#xff0c;最初是T…

JWT(JSON Web Token)简介及实现

JWT(JSON Web Token)&#xff1a;是一个开放标准(RFC 7519)&#xff0c;它定义了一种紧凑且自包含的方式&#xff0c;用于在各方之间作为Json对象安全地传输信息。由于此信息是经过数字签名的&#xff0c;因此可以被验证和信任。可以使用HMAC SHA256或RSA等对JWT进行签名。 JW…

iOS UIImageView 加载含有汉字的url处理方法

NSString *url [model.pic stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; [self.headImgView sd_setImageWithURL:[NSURL URLWithString:url]];

《评人工智能如何走向新阶段》后记

由AI科技大本营下载自视觉中国自《评人工智能如何走向新阶段》一文发表&#xff08;在内部&#xff09;后&#xff0c;引来了中外专家、草根们的广泛议论&#xff0c;有深有浅&#xff0c;其中似有一些思考价值&#xff0c;故录入本文后记&#xff1a; 中外专家、草根们23条议…

用XCA(X Certificate and key management)可视化程序管理SSL 证书(3)--创建自己定义的凭证管理中心(Certificate Authority)...

在第“用XCA&#xff08;X Certificate and key management&#xff09;可视化程序管理SSL 证书&#xff08;2&#xff09;---创建证书请求”章节中&#xff0c;我们介绍了怎样用XCA创建SSL证书请求&#xff08;Certificate Request&#xff09;&#xff0c;在一章节中&#xf…

C和C++安全编码笔记:并发

并发是一种系统属性&#xff0c;它是指系统中几个计算同时执行&#xff0c;并可能彼此交互。一个并发程序通常使用顺序线程和(或)进程的一些组合来执行计算&#xff0c;其中每个线程和进程执行可以在逻辑上并行执行的计算。这些进程和(或)线程可以在单处理器系统上使用分时抢占…

《评人工智能如何走向新阶段》后记(再续1)

由AI科技大本营下载自视觉中国中外专家、草根对《评人工智能如何走向新阶段》一文进行广泛议论&#xff0c;已在《后记》中发表原创&#xff08;未加修改&#xff09;的23条议论&#xff0c;现再续发24-30条如下&#xff1a; 24.最近半年来&#xff0c;人工智能的发展重心逐渐…

iOS UITextView 随键盘弹出界面上移

- (void)textViewDidBeginEditing:(UITextView *)textView { CGRect frame textView.frame; int offSet frame.origin.y 70 - (self.view.frame.size.height - 216.0); //iphone键盘高度为216.iped键盘高度为352 [UIView beginAnimations:"ResizeForKeyboard" co…

H3C 交换机命名规则

例&#xff1a;H3C-S5500-28C-EIH3C&#xff1a;为固定值&#xff0c;就是“H3C”这个品牌S的位置&#xff1a;代表产品系列『S 代表交换机SR 代表业务路由器』第一个5的位置:代表产品子系列号『3系为千兆上行,百兆下行的合适交换机 例:S3600 S31005系为全千兆的盒式交换机 …

iOS 时间选择器封装(含三种模式)

#import <UIKit/UIKit.h> typedef enum : NSUInteger { DatePickerViewDateTimeMode,//年月日,时分 DatePickerViewDateMode,//年月日 DatePickerViewTimeMode//时分 } DatePickerViewMode; protocol DateTimePickerViewDelegate <NSObject> optional /** * 确定按…

C和C++安全编码笔记:总结

《C和C安全编码》(原书第2版)这本书是2013年出版的。 这里是基于之前所有笔记的简单总结&#xff0c;笔记列表如下&#xff1a; 字符串&#xff1a;https://blog.csdn.net/fengbingchun/article/details/105325508 指针诡计&#xff1a;https://blog.csdn.net/fengbingchun/…

《评人工智能如何走向新阶段》后记(再续2)

由AI科技大本营下载自视觉中国从朋友那里获知&#xff0c;有一块供大家自由议论人工智能的园地&#xff08;内部的&#xff09;&#xff0c;我通过有关关系进入后&#xff0c;一览之余&#xff0c;果然生动活泼&#xff0c;没有学究气&#xff0c;从已发表的30条议论来看。有原…