Serious and Easy Crypto With AES/GCM
By: Yaşar Yücel Yeşilbağ
Tags: Aes Gcm, Cryptography, Dotnet Core, Csharp, Cross Platform

First things first, here are some definitions:

Key: A byte array that both parties have, 128-bit (16 bytes)

Nonce: A number used once, 96-bit (12 bytes)

Authorization data: A public text from sender, arbitrary size.

Authorization tag: A byte array created at sender side, 128-bit (16 bytes)

Plain text: Data to be encrypted, can be text or binary, arbitrary size.

Cipher text: Encrypted data, same size as plain data.

4 of these components should be transmitted/received by communicating parties; nonce, cipher, authorization tag and authorization data. Below is the structure for these 4 components, considered as the data package to be carried over i.e. a network.

public struct AESData

{

public string nonce;

public string cipher;

public string authTag;

public string authData;

}

Encrypted data is essentially a byte array, containing non-ASCII characters. We’ll use base64 encoding to convert byte arrays to strings, so the package can be sent and received over any text-based communication medium.

Encryption

AES/GCM, when encrypting, takes the key, nonce, authorization data and plain text as input, gives cipher text and authorization tag as output.

Plain text gets encrypted using the key and the nonce, creating cipher text. Then, authorization data is mixed with cipher text using the key, resulting 128-bit authorization tag, which is to prove both authenticity and integrity of the message.

Below piece of code shows how encryption is done in C#.

// declare aes variables

byte[] key = new byte[16];

byte[] nonce = new byte[12];

byte[] authTag = new byte[16];

byte[] authData = utf8enc.GetBytes("Auth data");

// data to be transmitted and received in base64 encoding

AESData aesData = new AESData();

// assign plain text

string plainText = "Hello AES/GCM! Some non-standard chars: öçşığü";

// convert the plain text string to a byte array

byte[] plainBytes = utf8enc.GetBytes(plainText);

// allocate the cipher text byte array as the same size as the plain text byte array

byte[] cipher = new byte[plainBytes.Length];

// perform encryption

using (AesGcm aesgcm = new AesGcm(key)) aesgcm.Encrypt(nonce, plainBytes, cipher, authTag, authData);

// encode aes data to Base64 strings, which will be transmitted

aesData.nonce = Convert.ToBase64String(nonce);

aesData.cipher = Convert.ToBase64String(cipher);

aesData.authTag = Convert.ToBase64String(authTag);

aesData.authData = Convert.ToBase64String(authData);

Decryption

AES/GCM, when decrypting, takes the key, nonce, authorization data, authorization tag and cipher text as input, gives plain text as output.

Authorization data is mixed with cipher text using the key, resulting 128-bit authorization tag. If this calculated tag matches the received tag, then the message is really sent by the sender, since only the person with the correct key can create that authorization tag. Then, cipher text gets decrypted using the key and the nonce, creating plain text.

Below piece of code shows how decryption is done in C#.

// decode received Base64 strings to aes data

nonce = Convert.FromBase64String(aesData.nonce);

cipher = Convert.FromBase64String(aesData.cipher);

authTag = Convert.FromBase64String(aesData.authTag);

authData = Convert.FromBase64String(aesData.authData);

// allocate the decrypted text byte array as the same size as the plain text byte array

byte[] decryptedBytes = new byte[cipher.Length];

// perform decryption

using (AesGcm aesgcm = new AesGcm(key)) aesgcm.Decrypt(nonce, cipher, authTag, decryptedBytes, authData);

// convert the byte array to the plain text string

string decryptedText = utf8enc.GetString(decryptedBytes);

What about nonce?

So far we got data authenticity, integrity and confidentiality, without using nonce value. But what if an eavesdropper saves a copy of a package, despite being unable to see the plain content, send it to receiver at a later time. How the receiver can determine whether the package is from the real sender or an eavesdropper? This is called replay attack.

Nonce value can be used to have protection against replay attack. Communicating parties may both have a record of nonce value of zero at the beginning. Every time one party preparing an AES package, may increase nonce value by one and use that value. Receiver may check if nonce value in the received package is greater than the last value of nonce on its record or not. If it’s not, then that package is a replayed package, so receiver discards it.