使用AesGcm类 [英] Using the AesGcm class
问题描述
我只是注意到.NET Standard 2.1/.NET Core 3.0最终添加了
I just noticed that .NET Standard 2.1/.NET Core 3.0 finally added a class for AES-GCM encryption.
However, its API seems to be slightly different from the usual .NET crypto classes: Its Encrypt
function asks for pre-allocated byte arrays for the cipher text and the tag, instead of providing them itself. Unfortunately there is no example in the docs showing proper usage of that class.
从理论上讲,我知道如何计算AES加密的预期密文大小,但是我想知道这是否真的是一种猜测"那里密文缓冲区大小的方法.通常,加密库提供负责这些计算的功能.
I know how to calculate the expected cipher text size for an AES encryption in theory, but I wonder whether it is really the intended approach to kind of "guess" a buffer size for the cipher text there. Usually crypto libraries provide functions that take care of those calculations.
有人举过一个例子,说明如何使用 AesGcm
正确加密字节数组吗?
Does someone have an example on how to properly encrypt a byte array using AesGcm
?
推荐答案
我现在已经知道了.
我忘记了在GCM中,密文具有与纯文本相同的长度;与其他加密模式(例如CBC)相反,不需要填充.随机数和标记的长度分别由 AesGcm
的 NonceByteSizes
和 TagByteSizes
属性确定.
I forgot that in GCM, the cipher text has the same length as the plain text; contrary to other encryption modes like CBC, no padding is required. The nonce and tag lengths are determined by the NonceByteSizes
and TagByteSizes
properties of AesGcm
, respectively.
使用此方法,可以通过以下方式进行加密:
Using this, encryption can be done in the following way:
public string Encrypt(string plain)
{
// Get bytes of plaintext string
byte[] plainBytes = Encoding.UTF8.GetBytes(plain);
// Get parameter sizes
int nonceSize = AesGcm.NonceByteSizes.MaxSize;
int tagSize = AesGcm.TagByteSizes.MaxSize;
int cipherSize = plainBytes.Length;
// We write everything into one big array for easier encoding
int encryptedDataLength = 4 + nonceSize + 4 + tagSize + cipherSize;
Span<byte> encryptedData = encryptedDataLength < 1024
? stackalloc byte[encryptedDataLength]
: new byte[encryptedDataLength].AsSpan();
// Copy parameters
BinaryPrimitives.WriteInt32LittleEndian(encryptedData.Slice(0, 4), nonceSize);
BinaryPrimitives.WriteInt32LittleEndian(encryptedData.Slice(4 + nonceSize, 4), tagSize);
var nonce = encryptedData.Slice(4, nonceSize);
var tag = encryptedData.Slice(4 + nonceSize + 4, tagSize);
var cipherBytes = encryptedData.Slice(4 + nonceSize + 4 + tagSize, cipherSize);
// Generate secure nonce
RandomNumberGenerator.Fill(nonce);
// Encrypt
using var aes = new AesGcm(_key);
aes.Encrypt(nonce, plainBytes.AsSpan(), cipherBytes, tag);
// Encode for transmission
return Convert.ToBase64String(encryptedData);
}
相应地,解密如下:
public string Decrypt(string cipher)
{
// Decode
Span<byte> encryptedData = Convert.FromBase64String(cipher).AsSpan();
// Extract parameter sizes
int nonceSize = BinaryPrimitives.ReadInt32LittleEndian(encryptedData.Slice(0, 4));
int tagSize = BinaryPrimitives.ReadInt32LittleEndian(encryptedData.Slice(4 + nonceSize, 4));
int cipherSize = encryptedData.Length - 4 - nonceSize - 4 - tagSize;
// Extract parameters
var nonce = encryptedData.Slice(4, nonceSize);
var tag = encryptedData.Slice(4 + nonceSize + 4, tagSize);
var cipherBytes = encryptedData.Slice(4 + nonceSize + 4 + tagSize, cipherSize);
// Decrypt
Span<byte> plainBytes = cipherSize < 1024
? stackalloc byte[cipherSize]
: new byte[cipherSize];
using var aes = new AesGcm(_key);
aes.Decrypt(nonce, cipherBytes, tag, plainBytes);
// Convert plain bytes back into string
return Encoding.UTF8.GetString(plainBytes);
}
有关完整的实现和示例,请参见 dotnetfiddle .
See dotnetfiddle for the full implementation and an example.
请注意,我是为网络传输编写的,因此所有内容都编码为一个大的base-64字符串;或者,您可以通过 out
参数分别返回 nonce
, tag
和 cipherBytes
.
Note that I wrote this for network transmission, so everything is encoded into one, big base-64 string; alternatively, you can return nonce
, tag
and cipherBytes
separately via out
parameters.
网络设置也是我发送随机数和标记大小的原因:该类可能被具有不同运行时环境(可能具有不同支持的参数大小)的不同应用程序使用.
The network setting is also the reason why I send the nonce and tag sizes: The class might be used by different applications with different runtime environments, which might have different supported parameter sizes.
这篇关于使用AesGcm类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!