by Stan Drapkin
- Wraps AesGcm and enforces AesGcm Tag to be exactly
16
bytes. UseAesGcmStrict
instead of AesGcm. - AesGcm allows truncated Tags: any AesGcm-provided Tag truncated to ex. 12 bytes will successfully decrypt.
Span<byte> plaintext = Encoding.UTF8.GetBytes("Hello World!");
Span<byte> key = new byte[32];
Span<byte> nonce = new byte[12];
Span<byte> ciphertext = new byte[plaintext.Length];
Span<byte> tag = new byte[16]; // generating a 16-byte Tag!
using var gcm = new AesGcm(key);
Console.WriteLine(Encoding.UTF8.GetString(plaintext));
gcm.Encrypt(nonce, plaintext, ciphertext, tag);
plaintext.Clear();
tag = tag.Slice(0, 12); // truncating the Tag to ex. 12 bytes
gcm.Decrypt(nonce, ciphertext, tag, plaintext); // decrypts successfully (PROBLEM)
Console.WriteLine(Encoding.UTF8.GetString(plaintext));
Most users of AesGcm might expect ~128 bits of Tag-security, but effectively get only ~96 bits at best.
- Add the namespace:
using SecurityDriven;
- Replace
AesGcm
withAesGcmStrict
// using SecurityDriven;
Span<byte> plaintext = Encoding.UTF8.GetBytes("Hello World!");
Span<byte> key = new byte[32];
Span<byte> nonce = new byte[12];
Span<byte> ciphertext = new byte[plaintext.Length];
Span<byte> tag = new byte[16]; // generating a 16-byte Tag!
using var gcm = new AesGcmStrict(key); // switching to AesGcmStrict
Console.WriteLine(Encoding.UTF8.GetString(plaintext));
gcm.Encrypt(nonce, plaintext, ciphertext, tag);
plaintext.Clear();
tag = tag.Slice(0, 12); // truncating the Tag to ex. 12 bytes
gcm.Decrypt(nonce, ciphertext, tag, plaintext); // throws ArgumentException (tag must be 16 bytes)
Console.WriteLine(Encoding.UTF8.GetString(plaintext));