• 注意: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. TokenObtainPairSerialize和TokenObtainPairView

    TokenObtainPairSerializer和TokenObtainPairView是Django REST framework的SimpleJWT库提供的两个相关的类. TokenObtain ...

  2. 强烈推荐:18.3k star,推荐一款简单易用的HTTP请求流量录制回放工具:Goreplay

    在软件开发和测试过程中,我们经常需要对应用程序的网络请求进行录制和回放,以便进行性能分析.压力测试或者模拟复杂的网络环境.今天,我要向大家推荐一款简单易用的 HTTP 请求流量录制回放工具:Gorep ...

  3. 结构体_C

    // Code file created by C Code Develop #include "ccd.h" #include "stdio.h" #incl ...

  4. Vue 基于VSCode结合Vetur+ESlint+Prettier统一Vue代码风格

    基于VSCode结合Vetur+ESlint+Prettier统一Vue代码风格 插件安装 安装Vetur,ESlint, Prettier - Code formatter插件 安装方法(安装ESl ...

  5. for循环以及常用的遍历(迭代)用法

    for循环以及常用的遍历(迭代)用法   概念:(概念才是高楼的地基!) for循环是一个计次循环,一般运用在循环次数已知的情况下.通常适用于枚举或遍历序列,以及迭代序列中的元素. 注意*:迭代变量用 ...

  6. 跟着ChatGPT学习设计模式 - 工厂模式

    1. 前言 在工作过程中,越发觉得设计模式的重要性.经常会有人说工作5年的人,大学生随便培训1-2月也能做同样的工作,没错,大学生的确可以做. 但其写的代码,可维护性.可扩展性.添加新功能时方便还是简 ...

  7. 巧用 QLineF 从 QTransform 提取角度

    我们在对 QGraphicsItem 进行变换时,QT 提供了很多便捷的方法.但当我们想获取当前变换的角度时却有些困难,因为 QTransform 没有提供获取角度的方法.在文章Qt 从 QTrans ...

  8. 【AppStore】IOS应用上架Appstore的一些小坑

    前言 上一篇文章写到如何上架IOS应用到Appstore,其中漏掉了些许期间遇到的小坑,现在补上 审核不通过原因 5.1.1 Guideline 5.1.1 - Legal - Privacy - D ...

  9. "基础模型时代的机器人技术" —— Robotics in the Era of Foundation Models

    翻译: 2023年是智能机器人规模化的重要一年!对于机器人领域之外的人来说,要传达事物变化的速度和程度是有些棘手的.与仅仅12个月前的情况相比,如今人工智能+机器人领域的大部分景观似乎完全不可识别.从 ...

  10. 强化学习中经典算法 —— reinforce算法 —— (进一步理解, 理论推导出的计算模型和实际应用中的计算模型的区别)

    在奖励折扣率为1的情况下,既没有折扣的情况下,reinforce算法理论上可以写为: 但是在有折扣的情况下,reinforce算法理论上可以写为: 以上均为理论模型. ================ ...