C# (.NET 7) and AES GCM

.NET is a standard software platform that manages executable code. With .NET 7, Microsoft further advanced their .NET Core infrastructure…

C# (.NET 7) and AES GCM

.NET is a standard software platform that manages executable code. With .NET 1.0, 2.0, 3.0 and 4.0, we have a standalone framework, and which was seperate from .NET Core 1.0, 2.0 and 4.0. Overal .NET Core was focused on creating a more robust Web-based environment, But, with .NET 5, Microsoft produced a unified platform — and which merged the two :

Ref [here]

With .NET 7, Microsoft further advanced their .NET Core infrastructure, and which should produce faster and more reliable code than previous .NET versions. In this case, we will use .NET 7.0, and which added an implementation AES GCM (and which is the most popular mode for AES encryption).

AES GCM

The workhorse of the cybersecurity industry is AES (Advanced Encryption Standard) and which is used to encrypt and decrypt data. The method comes from the winner of a NIST competition in 2001, and was previously known as the Rijndael (“Rain Dahl”) cipher.

AES is a symmetric key method, and where Bob and Alice have the same encryption key. In the following, Bob and Alice share an encryption key, and where Bob converts his plaintext into ciphertext, and then Alice converts the ciphertext back into plaintext using a shared secret key:

The problem with this setup is that the same plaintext will always result in the same ciphertext, so we typically add salt into the encryption process. We also need a way for Bob and Alice to generate the same secret key. This is either typically done through a key exchange method (such as with the Diffie-Hellman method) or by a KDF (Key Derivation Function). One of the most popular KDFs is PBKDF2 and which allows a password to be converted into an encryption key of a defined size:

The size of the key is typically either 128 bits or 256 bits. AES (Advanced Encryption Standard) can be applied in three modes:

  • Block cipher. This can be implemented with CBC (Cipher Block Chaining) and which implements a block cipher. In the case of AES, the block size will be 16 bytes, and thus the ciphertext will be a multiple of the block size. As we use a block cipher, we need to pad the data for the cipher process, and then unpad the decrypted data. The most common method is PKCS7, and which pads with the value which equals the number of padding bytes.
  • AEAD (Authenticated Encryption with Additional Data). This can be implemented with GCM (Galois Counter Mode) and which implements a stream cipher with the addition of additional data. This additional data can include something related to the ciphertext, such as with a session ID or TCP port. There is no padding required for the plaintext text, and thus the ciphertext will have the same length as the plaintext.
  • Stream cipher. This can be implemented with CFB (Cipher FeedBack) and which implements a stream cipher. As we use a stream cipher, we do not need to pad the data, and where the ciphertext size will be the same as the plaintext. Overall we use a simple XOR operation between the plaintext stream and a key stream (derived from the main encryption key). The decryption is performed by just XOR’ing the ciphertext stream with the same key stream.

So, let’s implement GCM using C#.

Coding

We can create a Dotnet console project for .NET 7.0 with:

dotnet new console --framework net7.0

This produces a Csproject file of:

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

Next, we can add the code of [here]:

namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
var password="Test";
var plaintext="Test2";
if (args.Length >0) plaintext=args[0];
if (args.Length >1) password=args[1];

var keygen = new System.Security.Cryptography.Rfc2898DeriveBytes(password, 64, 10000);
var key = keygen.GetBytes(32);
var aesGcm = new System.Security.Cryptography.AesGcm(key);
var plainBytes = System.Text.Encoding.UTF8.GetBytes(plaintext);
var IV = keygen.GetBytes(12);
var tag = new byte[16];
var associatedData = new byte[12];
var cipherText = new byte[plainBytes.Length];

aesGcm.Encrypt(IV, plainBytes,cipherText, tag, associatedData);

var plain = new byte[cipherText.Length];

aesGcm.Decrypt(IV, cipherText, tag, plain, associatedData);

Console.WriteLine("Plaintext: {0}",plaintext);
Console.WriteLine("Password: {0}",password);
Console.WriteLine("IV: {0} [{1}]",Convert.ToBase64String(IV),Convert.ToHexString(IV));
Console.WriteLine("Key: {0} [{1}]",Convert.ToBase64String(key),Convert.ToHexString(key));
Console.WriteLine("\nCipher: {0} [{1}]",Convert.ToBase64String(cipherText),Convert.ToHexString(cipherText));
Console.WriteLine("Plain text: {0}",System.Text.Encoding.UTF8.GetString(plain));
}
}
}

A sample run shows [here]:

Plaintext: Secret message
Password: qwerty123

IV: zthuHKFfogACxdKp [EB7D089D8ADC2FF467637E5E37D08530CD3B750E7369507CF02F58CE88ED6528]
Key: 630InYrcL/RnY35eN9CFMM07dQ5zaVB88C9YzojtZSg= [EB7D089D8ADC2FF467637E5E37D08530CD3B750E7369507CF02F58CE88ED6528]

Cipher: tz0koW2OlOKbrVyYEeo= [B73D24A16D8E94E29BAD5C9811EA]
Plain text: Secret message

Conclusions

Microsoft have made significant process in integrating cryptography into the .NET 7 framework. Here is some more C# programs:

https://asecuritysite.com/csharp

and some PowerShell:

https://asecuritysite.com/powershell