• 注意:AEAD_AES_256_GCM Key的长度必须是32位,nonce的长度必须是12位,附加数据有可能为空值。AEAD_AES_128_GCM Key的长度必须是16位,nonce的长度必须是12位,附加数据有可能为空值。

使用中AEAD_AES_256_GCM还是AEAD_AES_128_GCM加密,是根据key的长度来决定的。
size = key.Length * 8
256 = 32 * 8, AEAD_AES_256_GCM的key长度必须是 32 位。
128 = 16 * 8, AEAD_AES_128_GCM的key长度必须是 16 位。

英文好的可以看这个文档rfc5116

使用官方AesGcm类

自aspnetcore3.0之后,System.Security.Cryptography支持 AES_GCM,不支持.net framework。在加密时,请使用AesGcmEncryptToBase64_WithTag方法,这个方法的结果包含了tag (authentication tag)。加密结果最后面的16位字符就是tag,但是官方的加密方法没有帮我们拼接上。

/// <summary>
/// 使用 AesGcm 解密
/// </summary>
/// <param name="key">key32位字符</param>
/// <param name="nonce">随机串12位</param>
/// <param name="encryptedData">密文(Base64字符)</param>
/// <param name="associatedData">(可能null)</param>
/// <returns></returns>
static string AesGcmDecryptFromBase64(string key, string nonce, string encryptedData, string associatedData)
{
var keyBytes = Encoding.UTF8.GetBytes(key);
var nonceBytes = Encoding.UTF8.GetBytes(nonce);
var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData); var encryptedBytes = Convert.FromBase64String(encryptedData);
//tag size is 16
var cipherBytes = encryptedBytes[..^16];
var tag = encryptedBytes[^16..];
var decryptedData = new byte[cipherBytes.Length];
using var cipher = new AesGcm(keyBytes);
cipher.Decrypt(nonceBytes, cipherBytes, tag, decryptedData, associatedBytes);
return Encoding.UTF8.GetString(decryptedData);
} /// <summary>
/// 使用 AesGcm AEAD_AES_256_GCM 加密,不要在正式环境中使用这个方法。因为在解密时不知道tag,除非额外返回tag。
/// </summary>
/// <param name="key">key32位字符</param>
/// <param name="nonce">随机串12位</param>
/// <param name="plainData">明文</param>
/// <param name="associatedData">附加数据(可能null)</param>
/// <returns>只返回加密数据不包含authentication tag</returns>
static string AesGcmEncryptToBase64(string key, string nonce, string plainData, string associatedData)
{
var keyBytes = Encoding.UTF8.GetBytes(key);
var nonceBytes = Encoding.UTF8.GetBytes(nonce);
var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData); var plainBytes = Encoding.UTF8.GetBytes(plainData);
var cipherBytes = new byte[plainBytes.Length];
using var cipher = new AesGcm(keyBytes);
//tag size must be is 16
var tag = new byte[16];
cipher.Encrypt(nonceBytes, plainBytes, cipherBytes, tag, associatedBytes); return Convert.ToBase64String(cipherBytes);
} /// <summary>
/// 使用 AesGcm进行AEAD_AES_256_GCM加密
/// </summary>
/// <param name="key">key32位字符</param>
/// <param name="nonce">随机串12位</param>
/// <param name="plainData">明文</param>
/// <param name="associatedData">附加数据(可能null)</param>
/// <returns>base64(加密后数据 + authentication tag)</returns>
static string AesGcmEncryptToBase64_WithTag(string key, string nonce, string plainData, string associatedData)
{
var keyBytes = Encoding.UTF8.GetBytes(key);
var nonceBytes = Encoding.UTF8.GetBytes(nonce);
var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData); var plainBytes = Encoding.UTF8.GetBytes(plainData);
var cipherBytes = new byte[plainBytes.Length];
//tag size is 16
var tag = new byte[16];
using var cipher = new AesGcm(keyBytes);
cipher.Encrypt(nonceBytes, plainBytes, cipherBytes, tag, associatedBytes); var cipherWithTag = new byte[cipherBytes.Length + tag.Length];
Buffer.BlockCopy(cipherBytes, 0, cipherWithTag, 0, cipherBytes.Length);
Buffer.BlockCopy(tag, 0, cipherWithTag, cipherBytes.Length, tag.Length); return Convert.ToBase64String(cipherWithTag);
}

测试代码

var text = "{'A':123, count:'10', isOk:false, body:{'Text':'select * from table_A where name=@_p1', result:[{'id':1, 'age':23}]}}";
//KEY 必须是两个32位
var key = "1234567890_1234567890_1234567890"; var nonce = "77d0a5ff3937";//Guid.NewGuid().ToString("N").Substring(0, 12); var associated = "6df132d42d0b4581"; //Guid.NewGuid().ToString("N").Substring(0, 16); var pythonResult = "PrTO/594j0CYMi2CQF9IFIp7UNkiTtIiIUbmR+jv1c1iO8Ng/HDFHDjL2t0DYo7xo5Vr0O0fUg9hD3bfCoomP+taVaPrW2kJbPTiFXkohXk3T80lQIdWP5lrl21vJvZO3MbmvshyjU+Oxk7pSnjiE5mw/sPXBs4jzS5wtvLUgHvWGaNxzw=="; Console.WriteLine(); var cipherText = AesGcmEncryptToBase64(key, nonce, text, nonce); Console.WriteLine($"原始密文Base64 :\t{cipherText}"); //Console.WriteLine($"密文tag Base64:\t\t{AesGcmEncryptToBase64(keyBytes, nonceBytes, text, associatedBytes)}"); Console.WriteLine($"Python GCM密文 :\t{pythonResult}"); var cryptText1 = AesGcmEncryptByBouncyCastle(key, nonce, text, associated);
Console.WriteLine($"BouncyCastle密文: \t{cryptText1} "); var cryptText2 = AesGcmEncryptToBase64_WithTag(key, nonce, text, associated);
Console.WriteLine($"密文+Tag Base64 : \t{cryptText2} "); Console.WriteLine();
Console.WriteLine(); var t30 = AesGcmDecryptByBouncyCastle(key, nonce, pythonResult, associated);
Console.WriteLine($"BouncyCastle 解密 Python :{t30} \tisOk:{text == t30}"); var t40 = AesGcmDecryptFromBase64(key, nonce, pythonResult, associated);
Console.WriteLine($"AesGcm 解密 Python :{t40} \tisOk:{text == t40}"); Console.WriteLine();
Console.WriteLine(); var t31 = AesGcmDecryptByBouncyCastle(key, nonce, cryptText1, associated);
Console.WriteLine($"BouncyCastle 解密 BouncyCastle:{t31} \tisOk:{text == t31}"); var t41 = AesGcmDecryptFromBase64(key, nonce, cryptText1, associated);
Console.WriteLine($"AesGcm 解密 BouncyCastle:{t41} \tisOk:{text == t41}"); Console.WriteLine();
Console.WriteLine(); var t32 = AesGcmDecryptByBouncyCastle(key, nonce, cryptText2, associated);
Console.WriteLine($"BouncyCastle 解密 密文+Tag :{t32} \tisOk:{text == t32}"); var t42 = AesGcmDecryptFromBase64(key, nonce, cryptText2, associated);
Console.WriteLine($"AesGcm 解密 密文+Tag :{t42} \tisOk:{text == t42}");

转载来源:https://www.cnblogs.com/jzblive/p/14386757.html

C# 中的 AEAD_AES_256_GCM的更多相关文章

  1. Python开源框架

    info:更多Django信息url:https://www.oschina.net/p/djangodetail: Django 是 Python 编程语言驱动的一个开源模型-视图-控制器(MVC) ...

  2. 项目中使用libsodium扩展

    前段时间研究了微信小微商户,地址:https://pay.weixin.qq.com/wiki/doc/api/xiaowei.php?chapter=19_11 其接口操作中需要下载证书针对返回的密 ...

  3. Java中的微信支付(2):API V3 微信平台证书的获取与刷新

    1. 前言 在Java中的微信支付(1):API V3版本签名详解一文中胖哥讲解了微信支付V3版本API的签名,当我方(你自己的服务器)请求微信支付服务器时需要根据我方的API证书对参数进行加签,微信 ...

  4. mapreduce中一个map多个输入路径

    package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...

  5. Hadoop 中利用 mapreduce 读写 mysql 数据

    Hadoop 中利用 mapreduce 读写 mysql 数据   有时候我们在项目中会遇到输入结果集很大,但是输出结果很小,比如一些 pv.uv 数据,然后为了实时查询的需求,或者一些 OLAP ...

  6. Python中的多进程与多线程(一)

    一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...

  7. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  8. Angular杂谈系列1-如何在Angular2中使用jQuery及其插件

    jQuery,让我们对dom的操作更加便捷.由于其易用性和可扩展性,jQuer也迅速风靡全球,各种插件也是目不暇接. 我相信很多人并不能直接远离jQuery去做前端,因为它太好用了,我们以前做的东西大 ...

  9. 关于CryptoJS中md5加密以及aes加密的随笔

    最近项目中用到了各种加密,其中就包括从没有接触过得aes加密,因此从网上各种查,官方的一种说法: 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学 ...

  10. In-Memory:在内存中创建临时表和表变量

    在Disk-Base数据库中,由于临时表和表变量的数据存储在tempdb中,如果系统频繁地创建和更新临时表和表变量,大量的IO操作集中在tempdb中,tempdb很可能成为系统性能的瓶颈.在SQL ...

随机推荐

  1. oeasy教您玩转vim - 7 - # 从头插入

    另存与保存 回忆上节课内容 上次我们学会了另存为命令 : saveas {file} 还有这个直接保存命令 : w 真的可以把修改存了 下面我们来研究插入命令的细节. 插入命令 首先我们可以查询这个插 ...

  2. 题解:AT_abc352_d [ABC352D] Permutation Subsequence

    虽然比赛没打,但是想来水估值发表思路. 题意 给你一个 \(1\sim n\) 的排列,让你从中找一段长为 \(k\) 的子序列,使得这个子序列中的元素排序后数值连续. 分析 题意转换一下,先用结构体 ...

  3. golang轻量级的代码复制粘贴检查器 cpd

    golang轻量级的代码复制粘贴检查器 cpd 项目地址: https://github.com/dengjiawen8955/copy-paste-detector 快速开始 clone git c ...

  4. RPC和 HTTP协议

    RPC 和HTTP 的区别 服务发现 HTTP,知道服务域名,可以通过 DNS 解析 得到 服务的IP地址,从而进行访问 RPC 需要一个专门的中间服务去保存服务名和IP信息(注册中心,nacos.c ...

  5. (二)MongoDB的在SpringBoot中的应用

    我来填之前MongoDB的坑了,项目中又用到MongoDB的我又想起来了,我这拖延症也是没谁了. 1.在pom.xml中引入依赖 <dependency> <groupId>o ...

  6. Jax框架 —— 如何在没有GPU和TPU的设备上debug代码 —— 在CPU上使用GPU仿真设置 —— Jax框架在多卡设备上的自动并行特性的仿真体验

    Jax计算框架是Google用来取代Tensorflow的新一代计算框架,这个框架使用类似pytorch的技术,但是在pytorch技术之上加入了更加强大的技术,但是这也导致该框架使用起来要比pyto ...

  7. 始智AI —— https://wisemodel.cn/ —— 试用

    清华大学的合资企业推出的服务: 始智AI -- https://wisemodel.cn/ 链接: 始智AI -- https://wisemodel.cn/ 和modelscope比相对简约,毕竟功 ...

  8. 【转载】 解决运行docker命令要用sudo的问题

    将当前登录的用户添加到docker组中,这样以后在访问docker时就不用在sudo了 1. 查看是否创建docker 组 cat /etc/group | grep docker 2.创建docke ...

  9. 乌克兰学者的学术图谱case5

    ========================================== 背景: 弗兰采维奇材料问题研究是欧洲最大的材料科研院所,在核电.航空.航天.军工及其他装备制造领域的先进材料研制方 ...

  10. baselines算法库common/vec_env/subproc_vec_env.py模块分析

    模块代码: import multiprocessing as mp import numpy as np from .vec_env import VecEnv, CloudpickleWrappe ...