# Additional Authenticated Data for AES-GCM in Xojo

**URL:** <https://forum.xojo.com/t/additional-authenticated-data-for-aes-gcm-in-xojo/89186>\
**Category:** Extras\
**Created:** [November 11, 2026, 12:19pm UTC](https://forum.xojo.com/t/additional-authenticated-data-for-aes-gcm-in-xojo/89186 "2026-11-11T12:19:31Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Christian\_Schmitz](https://forum.xojo.com/user_avatar/forum.xojo.com/christian_schmitz/32/158_2.png) [@Christian\_Schmitz](https://forum.xojo.com/u/Christian_Schmitz)\
**Post date:** [November 11, 2026, 12:19pm UTC](https://forum.xojo.com/t/additional-authenticated-data-for-aes-gcm-in-xojo/89186/1 "2026-11-11T12:19:32Z")

</div>

With version 26.5 of the [MBS Xojo Plugins](https://www.monkeybreadsoftware.de/xojo/), the **[CipherMBS](https://www.monkeybreadsoftware.net/class-ciphermbs.shtml)** class gets two new methods: **ProcessStringAAD** and **ProcessMemoryAAD**. They let you pass _Additional Authenticated Data_ (AAD) to an AES-GCM encryption. Let us look at what this is, why you may want it and how to use it in your Xojo projects.

## A quick recap: AES-GCM

GCM (Galois/Counter Mode) is an _authenticated_ encryption mode. Besides encrypting your data, it calculates a 16 byte tag over the result. When you decrypt, you pass this tag back in, and the decryption only succeeds if nothing was changed. A flipped bit in the encrypted data, a wrong key or a wrong tag, and the decryption fails instead of handing you garbage.

[CipherMBS](https://www.monkeybreadsoftware.net/class-ciphermbs.shtml) supports GCM since a long time with the aes\_128\_gcm, aes\_192\_gcm and aes\_256\_gcm ciphers (and the ARIA variants). You query the tag with **GetGCMTag** after encrypting and set it with **SetGCMTag** before finalizing the decryption.

## What is Additional Authenticated Data?

Often you have data that does not need to be secret, but must not be tampered with. Think of:

- a header with a version number or the text encoding,
- a record ID or user ID the encrypted value belongs to,
- a file name, a timestamp or a protocol message header.

This data stays readable, e.g. so you can route a message or look up a record before decrypting. But you want to be sure nobody changed it. With AAD you feed this data into the GCM calculation. It is **not encrypted** and **not part of the output** , but it goes into the tag. To decrypt, you must provide exactly the same AAD again. If someone changed a single byte of it, the decryption fails.

A typical use case: you store encrypted values in a database and use the record ID as AAD. Now an attacker can’t copy the encrypted value from one record into another one, since the decryption would fail with the other record ID.

## The new methods

```xojo
ProcessStringAAD(data as String) as Boolean
ProcessMemoryAAD(data as MemoryBlock) as Boolean

```

Both return true on success. Call them after **EncryptInit** or **DecryptInit** and **before** you pass the actual data to ProcessString or ProcessMemory. You may call them several times to add more AAD.

## Example

Here is a full round trip. We encrypt a text with a header as AAD, then decrypt it again with the same header:

```xojo
Var key As String = "mysecretkey"
Var data As String = "Hello World. Just a test"
Var AAD As String = "encoding=UTF-8;"

// encrypt
Var c As CipherMBS = CipherMBS.aes_128_gcm
Call c.EncryptInit key

Call c.ProcessStringAAD(AAD)
Var Encrypted As String = c.ProcessString(data) + c.FinalizeAsString
Var GCMTag As MemoryBlock = c.GetGCMTag

// decrypt
c = CipherMBS.aes_128_gcm
Call c.DecryptInit key

c.SetGCMTag GCMTag
Call c.ProcessStringAAD(AAD)
Var Decrypted As String = c.ProcessString(Encrypted) + c.FinalizeAsString

Break // inspect in debugger

```

If the tag, the AAD or the encrypted data doesn’t match, the CipherMBS class raises an UnsupportedOperationException in ProcessString, so you never get unverified data back.

Please note that the AAD is passed in the same order as on encryption: first the AAD, then the encrypted data. The encrypted output has the same length as the input, as GCM works like a stream cipher. Nothing of the AAD ends up in there.

To store or transmit the result, you keep three pieces together: the AAD in plain text, the encrypted data and the tag. Since encrypted data and tag are binary, use EncodeBase64 or EncodeHex before you put them into a text field.

## Doing it right: key and IV

The example above is short to show the concept. For real use, please follow two rules:

**Use a proper key.** AES-128 needs a 16 byte key, AES-256 a 32 byte key. Instead of padding a password with zeros, hash it, e.g. with SHA-256 for AES-256. Even better, use a proper key derivation function with salt for passwords.

**Never reuse an IV with the same key.** If you don’t pass an IV, it is filled with zeros. For GCM, using the same key and IV twice is fatal: an attacker can learn about your data and even forge tags. So generate a new random IV for every encryption and store it with the result. The IV doesn’t need to be secret. For GCM, the IV is normally 12 bytes, which the IVLength property reports.

Here is a more complete example with AES-256, a random IV and a record ID as AAD:

```xojo
Var password As String = "mysecretkey"
Var key As MemoryBlock = Crypto.SHA2_256(password) // 32 bytes for AES-256
Var data As String = "Credit limit: 5000 EUR"
Var AAD As String = "customer=12345;"

// encrypt
Var c As CipherMBS = CipherMBS.aes_256_gcm
Var IV As MemoryBlock = Crypto.GenerateRandomBytes(c.IVLength)

Call c.EncryptInit key, IV
Call c.ProcessStringAAD(AAD)
Var Encrypted As String = c.ProcessString(data) + c.FinalizeAsString
Var Tag As MemoryBlock = c.GetGCMTag

// store IV + tag + encrypted data, AAD is known from the record
Var stored As String = EncodeBase64(IV + Tag + Encrypted, 0)

// decrypt
Var raw As String = DecodeBase64(stored)
Var IV2 As MemoryBlock = raw.LeftBytes(12)
Var Tag2 As MemoryBlock = raw.MiddleBytes(12, 16)
Var Encrypted2 As String = raw.MiddleBytes(28)

Var d As CipherMBS = CipherMBS.aes_256_gcm
Call d.DecryptInit key, IV2
d.SetGCMTag Tag2
Call d.ProcessStringAAD(AAD)

Try
  Var Decrypted As String = d.ProcessString(Encrypted2) + d.FinalizeAsString
  MessageBox Decrypted
Catch err As UnsupportedOperationException
  MessageBox "Decryption failed: data, tag or AAD was modified."
End Try

```

If you now change the AAD for the decryption to “customer=12346;”, you get the UnsupportedOperationException, even if key, IV, tag and encrypted data are all correct.

## Compatibility

Since [CipherMBS](https://www.monkeybreadsoftware.net/class-ciphermbs.shtml) uses OpenSSL, the result is standard AES-GCM. You can exchange data with other platforms and languages, e.g. with CryptoKit on Apple platforms, the Web Crypto API in JavaScript (the _additionalData_ parameter), Java’s Cipher.updateAAD() or .NET’s AesGcm class. Just make sure all sides agree on key, IV, tag length and of course the AAD bytes. Watch the text encoding: “Müller” in UTF-8 has different bytes than in Windows ANSI!

## Conclusion

Additional Authenticated Data is a small addition with a big benefit: you bind your encrypted data to its context. Headers, IDs and metadata stay readable, but can’t be changed or mixed up without being noticed.

The new methods are included in version 26.5 of the [MBS Xojo Encryption Plugin](https://www.monkeybreadsoftware.de/xojo/plugin-encryption.shtml) and work on macOS, Windows and Linux. Please try them and let us know if you have questions.

This article was drafted by AI from notes and edited by a human.
