我应该在AESGCM中使用迭代吗?
读到RijndaelManaged是 aesgcm (在.net core 3.1中引入。优于,我正在尝试实现 aesgcm 使用此答案。
这是我的代码:
/// Perform AES Encryption, returning the result as a byte array.
/// </summary>
/// <param name="bytesToEncrypt">string, file or data represented as byte array</param>
/// <param name="passwordBytes">A unique password for the encryption (must be 32 bytes?)</param>
/// <returns>The data encrypted</returns>
public byte[] EncryptData(byte[] bytesToEncrypt, byte[] passwordBytes)
{
// Based on https://stackoverflow.com/questions/60889345/using-the-aesgcm-class/60891115#60891115
// Get parameter sizes
int nonceSize = AesGcm.NonceByteSizes.MaxSize;
int tagSize = AesGcm.TagByteSizes.MaxSize;
int cipherSize = bytesToEncrypt.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(passwordBytes))
{
aes.Encrypt(nonce, bytesToEncrypt.AsSpan(), cipherBytes, tag);
}
return encryptedData.ToArray();
}
/// <summary>
/// Takes in an AES encrypted byte array, decrypts it and returns the resulting unencrypted byte array.
/// </summary>
/// <param name="encryptedBytes">A string, file or object represented as a byte array that's previously been encrypted.</param>
/// <param name="passwordBytes">The password used to encrypt the data. </param>
/// <returns></returns>
public byte[] DecryptData(byte[] encryptedBytes, byte[] passwordBytes)
{
// Decode
Span<byte> encryptedData = encryptedBytes.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(passwordBytes))
{
aes.Decrypt(nonce, cipherBytes, tag, plainBytes);
}
// Convert plain bytes back into string
return plainBytes.ToArray();
}
我注意到的一件事,似乎没有迭代的地方。
例如,在Aesmaned中,我总是像以下内容一样迭代,因为迭代使攻击变得更加复杂。我遵循了类似的模式,密码哈希:
// Set Symmetric encryption algorithm
// Based on http://stackoverflow.com/questions/27645527/aes-encryption-on-large-files
var AES = Aes.Create("AesManaged");
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.PKCS7;
//http://stackoverflow.com/questions/2659214/why-do-i-need-to-use-the-rfc2898derivebytes-class-in-net-instead-of-directly
//"What it does is repeatedly hash the user password along with the salt." High iteration counts.
var key = new Rfc2898DeriveBytes(passwordBytes, salt, 100000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
...
我感谢 nonce
会产生影响,但是我以前所做的一切都依赖多次迭代,所以似乎奇怪的是不在 AESGCM 。
AESGCM似乎没有迭代的手段。我应该在某个地方迭代一部分吗?如果我应该迭代,我该怎么做?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
rijndaelmanaged
已弃用,但它是一个实现类。您应该一直使用 aes.create 而不是很长一段时间,更喜欢no-argument构造函数。通常,这将为您提供优化的C/C ++版本,该版本可以利用CPU的一部分(很可能)的AES_NI指令集。使用.NET实现“托管”类,并且狗慢> 。AESGCM
可以并且应该直接使用,并在密码中添加了真实性和完整性。是的,不,那是不对的。密码不是密钥,AES在密钥上而不是密码。因此,缺少密钥(可能是IV)的部分(可能是IV)。这应该从您提到的上一个示例中复制。但是,您应该使用
int nonceize = aesgcm.noncebyize.maxsize
,因为gcm最适合96位/12个字节nonce(我想,我想给您的东西,原则上,GCM对于NONCE没有功能最大。当然,如果允许性能,则可以增加迭代次数。只要您应该为每个新的密文更改盐,就可以计算nonce ,就可以计算nonce。当心,如果盐和nonce 重复< / strong>重复出现,您的方案将非常失败,因此请确保使用128位 / 16字节盐。
没错,但这是因为它假定是一个完全随机的密钥。如果您有密码,则必须执行PBKDF2(
RFC2898DeriveBytes
class insterments)或其他基于密码的键推导功能。当心AES-GCM的上限为64 GIB(减去几个字节)。
更糟糕的是,它要求您将所有明文 /密文存储在缓冲区中。从这种意义上讲,它可能不是基于文件加密的最佳选择。您也可以使用GCM加密块,但是您需要在身份验证标签上执行HMAC,以确保未重新排序单独验证的块。
iv和ciphertext上的AES-CBC + HMAC可能是另一个选择。
RijndaelManaged
is deprecated but it is an implementation class. You should have been usingAes.Create
instead for a long time, preferring the no-argument constructor. Generally this will give you the optimized C/C++ version that can utilize the AES_NI instruction set that is - very likely - part of your CPU. The "Managed" classes are implemented using .NET and are comparably dog slow.AesGcm
can and should be used directly it seems, and adds authenticity and integrity to the cipher.Yes, no, that's not right. A password is not a key, and AES operates on keys, not passwords. So the part where the key (and possibly IV) are derived from the password is missing. This should be copied from the previous example that you mentioned. However, you should use
int nonceSize = AesGcm.NonceByteSizes.MaxSize
as GCM works best for a 96 bit / 12 byte nonce (which is, I suppose what that gives you, in principle GCM doesn't have a functional maximum size for the nonce).Of course, if performance permits, you can up the number of iterations. Calculating the nonce is fine, as long as you change the salt for each new ciphertext as it should. Beware that your scheme will horribly fail if the salt and nonce do repeat, so use a 128 bit / 16 byte salt just to be sure.
That's correct, but that's because it assumes a fully randomized key. If you have a password, you will have to perform PBKDF2 (which the badly named
Rfc2898DeriveBytes
class implements) or another password based key derivation function.Beware that AES-GCM has an upper limit of 64 GiB (minus a few bytes).
Worse, it requires you to store all the plaintext / ciphertext in a buffer. It may not be the best option for file based encryption in that sense. You can encrypt chunks with GCM as well, but then you need to e.g. perform a HMAC over the authentication tags to make sure that the separately authenticated chunks are not reordered.
AES-CBC + HMAC over IV and ciphertext could be another option.
第一个重要的一点是您的第二个样本从密码生成IV。 不要执行此操作!对于每个加密需要唯一的IV,尤其是在重复使用键时。您正在AES-GCM样本中正确执行此操作,在该样本中,您会生成一个随机的nonce,该nonce是在密文开始时发送的。
一个基本示例:想象一下您使用相同的共享键加密两条以同一文本开头的消息。如果您对两者都使用相同的IV,则两个密文也将相同。你不想要这个。
AES需要一个完全合适的键。
RFC2898DeriveBytes
用于将任意长度密码转换为具有正确数字字节数的密钥。在您的第二个示例中,passwordbytes
可能是任何长度。在您的AES-GCM示例中,
passwordBytes
直接传递给aesgcm
构造函数。因此,passwordbytes
必须已经是正确的长度。如果愿意,您可以在
rfc2898derivebytes
上使用passwordbytes
之前,然后将结果键传递到aesgcm
constructor。这将使您使用任何长度的passwordbytes
。The first important point is the your second sample generates the IV from the password. DO NOT DO THIS! The IV needs to be unique for each encryption, particularly if the key is re-used. You're doing this properly in your AES-GCM sample, where you generate a random nonce which is sent at the start of the ciphertext.
One basic example: imagine you encrypt two messages which start with the same text, using the same shared key. If you use the same IV for both, the two ciphertexts will also be identical. You do not want this.
AES requires a key which is exactly the right length.
Rfc2898DeriveBytes
is used to turn an arbitrary-length password into a key which has the correct number of bytes. In your second sample,passwordBytes
may be any length.In your AES-GCM sample,
passwordBytes
is passed directly to theAesGcm
constructor. Therefore,passwordBytes
must already be exactly the right length.If you wish, you can use
Rfc2898DeriveBytes
onpasswordBytes
before passing the resulting key to theAesGcm
constructor. This would let you use apasswordBytes
of any length.AES GCM 256在框架5及以上运行...
因此,首先使用框架5及以上编写程序
我已经写了一个示例类用来使用它和库
使用System.Security.Cryptography;
我在此类中添加了此类
,还有一个用于制作IV的函数,其中我使用了时间参数
AES GCM 256 Runs in framework 5 and above...
So, first write the program with framework 5 and above
I have written a sample class to use it and the library
using System.Security.Cryptography;
I have added to this class
In this class, there is also a function for making IV, in which I have used time parameters