---
title: Security Trailers
slug: security-trailers
docTags: 
createdAt: 2025-01-14T09:49:47.019Z
---

Every message sent to the Toro Gateway must include a valid Security Trailer.

For detailed guidance on the format of the Security Trailer, please see the Nexo Card Payment Protocols Security Message User Guide (MUG) which can be downloaded from [nexo-standards.org](https://nexo-standards.org).

The Toro Gateway requires implementers to provide a Security Trailer using the Authenticated Data type; in other words, your implementation should generate a MAC (Message Authentication Code) using one of the supported algorithms and specify this in the Security Trailer.

The Security Trailer protects the message using a MAC (Message Authentication Code).

MAC generation and MAC verification use the same algorithms. MAC is verified by generating the MAC from the received message, and compared to the received MAC.

At a high level, the steps to generate a security trailer are:

1. During onboarding, a shared passphrase is generated and provided
2. Key material is derived from the shared passphrase using PBKDF2
3. A MAC is calculated for a given message body using the derived key material
4. A security trailer is generated, setting the MAC field and other information

An example security trailer is shown below:

```xml
<SctyTrlr>
	<CnttTp>AUTH</CnttTp>
	<AuthntcdData>
		<Rcpt>
			<KeyIdr>
			  <KeyId>SpecV1TestKey</KeyId>
			  <KeyVrsn>1</KeyVrsn>
			</KeyIdr>
		</Rcpt>
		<MACAlgo>
			<Algo>CCA3</Algo>
		</MACAlgo>
		<NcpsltdCntt>
			<CnttTp>DATA</CnttTp>
		</NcpsltdCntt>
		<MAC>9xIobnJ/PyaB10EB4L6N4w==</MAC>
	</AuthntcdData>
</SctyTrlr>
```

# Derive Key Material

During onboarding to the Toro Platform, you will be provided with a passphrase which can be used to derive the relevant cryptographic material needed to generate and verify message security trailers.

In the sandbox environment, the following passphrase can be used by all integrating parties: `ToroGatewayNexoV1PassphraseDevOnly`

The passphrase is used in combination with a fixed salt to generate a 32-byte (256-bit) MAC key.

The process uses PBKDF2 (Password-Based Key Derivation Function 2) to generate cryptographic keys and an initialization vector (IV) from a single passphrase.

:::hint{type="info"}
Key material is derived from the shared passphrase, and only changes when the shared key changes. Therefore it is not necessary to derive key material for each message. However, the derived key material is secret, so if your implementation does not derive key material for every message, it is important to store the key material securely in your system.
:::

## Required Parameters

- `passphrase`: A string containing the secret passphrase
- `salt`: A string used as cryptographic salt. The salt value is fixed and should always be: `ToroGatewayNexoV1Salt`

## Fixed Parameters

- Iterations: 4000
- Output Length: 80 bytes
- Hash Function: SHA-256

## Derived output

The PBKDF2 function will generate an 80 byte output. This should be used as follows:

- CMAC key: bytes 1-32
- Cipher key: bytes 33-64
- Initialisation vector: bytes 65-80

## Code examples

:::CodeblockTabs
```bash
openssl kdf -keylen 80 -kdfopt digest:SHA256 -kdfopt iter:4000 -kdfopt salt:"ToroGatewayNexoV1Salt" -kdfopt pass:"ToroGatewayNexoV1PassphraseDevOnly" PBKDF2 | tr -d ':\n' > keymaterial.hex
# Expected contents of file keymaterial.hex:
# E05DCBA1276A3D822F38C7A6C45F2FCFD4BE8B0849588633F5CD9D210244EE8FF4D7DFE8F8E2F16FFD87ADF470DBEF42191986AF143F45C7F70046C05DAAE7FA50DF6BE87422B9EC129ECD1B67548485

# Extract CMAC key (first 64 hex chars = 32 bytes)
echo "CMAC key:"
cut -c 1-64 keymaterial.hex
# Expected: E05DCBA1276A3D822F38C7A6C45F2FCFD4BE8B0849588633F5CD9D210244EE8F

# Extract cipher key (next 64 hex chars = 32 bytes)
echo -e "\nCipher key:"
cut -c 65-128 keymaterial.hex
# Expected: F4D7DFE8F8E2F16FFD87ADF470DBEF42191986AF143F45C7F70046C05DAAE7FA

# Extract IV (last 32 hex chars = 16 bytes)
echo -e "\nIV:"
cut -c 129-160 keymaterial.hex
# Expected: 50DF6BE87422B9EC129ECD1B67548485
```

```php
function NexoDeriveKeymaterial($passphrase) {
    $outlen = 80;
    $salt =  "ToroGatewayNexoV1Salt";
    $rounds = 4000;
    $bytes = openssl_pbkdf2($passphrase, $salt, $outlen, $rounds, "sha256");
 
    $cmac_key = substr($bytes, 0, 32);
    $cipher_key = substr($bytes, 32, 32);
    $iv = substr($bytes, 64, 16);
 
    return array('cmac_key' => $cmac_key, 'cipher_key' => $cipher_key, 'iv' => $iv);
}
```

```python
import hashlib
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

def nexo_derive_keymaterial(passphrase: str) -> dict:
    salt = b"ToroGatewayNexoV1Salt"
    rounds = 4000
    outlen = 80
    
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=outlen,
        salt=salt,
        iterations=rounds,
    )
    
    derived = kdf.derive(passphrase.encode('utf-8'))
    
    return {
        'cmac_key': derived[0:32],
        'cipher_key': derived[32:64],
        'iv': derived[64:80]
    }
```

```csharp
using System.Security.Cryptography;

public class KeyDerivation
{
    public static Dictionary<string, byte[]> NexoDeriveKeymaterial(string passphrase)
    {
        byte[] salt = System.Text.Encoding.UTF8.GetBytes("ToroGatewayNexoV1Salt");
        int rounds = 4000;
        int outlen = 80;
        
        using (var pbkdf2 = new Rfc2898DeriveBytes(
            passphrase,
            salt,
            rounds,
            HashAlgorithmName.SHA256))
        {
            byte[] derived = pbkdf2.GetBytes(outlen);
            
            return new Dictionary<string, byte[]>
            {
                { "cmac_key", derived.Take(32).ToArray() },
                { "cipher_key", derived.Skip(32).Take(32).ToArray() },
                { "iv", derived.Skip(64).Take(16).ToArray() }
            };
        }
    }
}
```

```java
# Java Implementation
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.spec.KeySpec;

public class KeyDerivation {
    public static Map<String, byte[]> nexoDeriveKeymaterial(String passphrase) 
        throws Exception {
        byte[] salt = "ToroGatewayNexoV1Salt".getBytes(StandardCharsets.UTF_8);
        int rounds = 4000;
        int outlen = 80;
        
        KeySpec spec = new PBEKeySpec(
            passphrase.toCharArray(), 
            salt, 
            rounds, 
            outlen * 8  // KeySpec expects bits, not bytes
        );
        
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        byte[] derived = factory.generateSecret(spec).getEncoded();
        
        Map<String, byte[]> result = new HashMap<>();
        result.put("cmac_key", Arrays.copyOfRange(derived, 0, 32));
        result.put("cipher_key", Arrays.copyOfRange(derived, 32, 64));
        result.put("iv", Arrays.copyOfRange(derived, 64, 80));
        
        return result;
    }
}
```

```ruby
require 'openssl'

def nexo_derive_keymaterial(passphrase)
  salt = "ToroGatewayNexoV1Salt"
  rounds = 4000
  outlen = 80
  
  derived = OpenSSL::PKCS5.pbkdf2_hmac(
    passphrase,
    salt,
    rounds,
    outlen,
    OpenSSL::Digest::SHA256.new
  )
  
  {
    cmac_key: derived.byteslice(0, 32),
    cipher_key: derived.byteslice(32, 32),
    iv: derived.byteslice(64, 16)
  }
end
```

```go
package main

import (
    "golang.org/x/crypto/pbkdf2"
    "crypto/sha256"
)

func NexoDeriveKeymaterial(passphrase string) map[string][]byte {
    salt := []byte("ToroGatewayNexoV1Salt")
    rounds := 4000
    outlen := 80
    
    derived := pbkdf2.Key(
        []byte(passphrase),
        salt,
        rounds,
        outlen,
        sha256.New,
    )
    
    return map[string][]byte{
        "cmac_key":   derived[0:32],
        "cipher_key": derived[32:64],
        "iv":         derived[64:80],
    }
}
```

```nodejs
const crypto = require('crypto');

function nexoDeriveKeymaterial(passphrase) {
    const salt = "ToroGatewayNexoV1Salt";
    const rounds = 4000;
    const outlen = 80;
    
    const derived = crypto.pbkdf2Sync(
        passphrase,
        salt,
        rounds,
        outlen,
        'sha256'
    );
    
    return {
        cmac_key: derived.subarray(0, 32),
        cipher_key: derived.subarray(32, 64),
        iv: derived.subarray(64, 80)
    };
}
```

```kotlin
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.PBEKeySpec
import java.nio.charset.StandardCharsets

fun nexoDeriveKeymaterial(passphrase: String): Map<String, ByteArray> {
    val salt = "ToroGatewayNexoV1Salt".toByteArray(StandardCharsets.UTF_8)
    val rounds = 4000
    val outlen = 80
    
    val spec = PBEKeySpec(
        passphrase.toCharArray(),
        salt,
        rounds,
        outlen * 8  // KeySpec expects bits, not bytes
    )
    
    val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
    val derived = factory.generateSecret(spec).encoded
    
    return mapOf(
        "cmac_key" to derived.copyOfRange(0, 32),
        "cipher_key" to derived.copyOfRange(32, 64),
        "iv" to derived.copyOfRange(64, 80)
    )
}
```

```swift
import Foundation
import CommonCrypto

func nexoDeriveKeymaterial(passphrase: String) -> [String: Data] {
    let salt = "ToroGatewayNexoV1Salt".data(using: .utf8)!
    let rounds = 4000
    let outlen = 80
    
    var derivedKeyData = Data(repeating: 0, count: outlen)
    
    // Derive the key using PBKDF2
    let result = derivedKeyData.withUnsafeMutableBytes { derivedKeyBytes in
        salt.withUnsafeBytes { saltBytes in
            CCKeyDerivationPBKDF(
                CCPBKDFAlgorithm(kCCPBKDF2),                  // algorithm
                passphrase,                                    // password
                passphrase.lengthOfBytes(using: .utf8),        // passwordLen
                saltBytes.baseAddress?.assumingMemoryBound(    // salt
                    to: UInt8.self),
                salt.count,                                    // saltLen
                CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256),        // prf
                UInt32(rounds),                                // rounds
                derivedKeyBytes.baseAddress?.assumingMemoryBound(
                    to: UInt8.self),                          // derivedKey
                outlen                                         // derivedKeyLen
            )
        }
    }
    
    guard result == kCCSuccess else {
        fatalError("PBKDF2 computation failed")
    }
    
    return [
        "cmac_key": derivedKeyData.subdata(in: 0..<32),
        "cipher_key": derivedKeyData.subdata(in: 32..<64),
        "iv": derivedKeyData.subdata(in: 64..<80)
    ]
}
```
:::

## Implementation verification

To verify that your implementation is working as expected, please ensure that the following inputs result in the output shown.

Salt: `ToroGatewayNexoV1Salt`

Passphrase: `ToroGatewayNexoV1PassphraseDevOnly`

MAC key: `e0 5d cb a1 27 6a 3d 82 2f 38 c7 a6 c4 5f 2f cf d4 be 8b 08 49 58 86 33 f5 cd 9d 21 02 44 ee 8f`

Cipher key: `f4 d7 df e8 f8 e2 f1 6f fd 87 ad f4 70 db ef 42 19 19 86 af 14 3f 45 c7 f7 00 46 c0 5d aa e7 fa`

Initialisation Vector (IV): `50 df 6b e8 74 22 b9 ec 12 9e cd 1b 67 54 84 85`

# Security Trailer structure

A valid security trailer should be sent with every request. It should conform to the defined Nexo Standard and use the AuthenticatedMessage data structure. The relevant fields for ISO 20022 message component `ContentInformationType36` are shown below:

| **Level** | **Field Name**            | **Parent**                                            | **Abbreviation** | **Multiplicity**  | **Description**                                                                                                                                                                                                                                                                                                                                                                                              | **ISO 20022 Type**        |
| --------- | ------------------------- | ----------------------------------------------------- | ---------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------- |
| 0         | Security Trailer          | \[message container e.g. AcceptorCompletionAdviceV12] | SctyTrlr         | Mandatory         | Trailer of the message containing a MAC.                                                                                                                                                                                                                                                                                                                                                                     | ContentInformationType36  |
| 1         | Content Type              | Security Trailer                                      | CnttTp           | Mandatory         | Type of data protection.<br />Allowed values:<br />- `AUTH` (Authenticated Data)                                                                                                                                                                                                                                                                                                                             | ContentType2Code          |
| 1         | Authenticated Data        | Security Trailer                                      | AuthntcdData     | Mandatory         | Data protection by a message authentication code (MAC).                                                                                                                                                                                                                                                                                                                                                      | AuthenticatedData9        |
| 2         | Version                   | Authenticated Data                                    | Vrsn             | Optional          | Version of the data structure.<br />Restrictions:<br />- FractionDigits: 0<br />- TotalDigits: 18                                                                                                                                                                                                                                                                                                            | Number                    |
| 2         | Recipient                 | Authenticated Data                                    | Rcpt             | Repetition (1..n) | Session key or protection key identification used by the recipient.                                                                                                                                                                                                                                                                                                                                          | Recipient14Choice         |
| 3         | Key Identifier            | Recipient                                             | KeyIdr           | Choice            | Identification of a protection key without a session key, shared and previously exchanged between the initiator and the recipient.                                                                                                                                                                                                                                                                           | KEKIdentifier7            |
| 4         | Key Identification        | Key Identifier                                        | KeyId            | Mandatory         | Identification of the cryptographic key.                                                                                                                                                                                                                                                                                                                                                                     | Max140Text                |
| 4         | Key Version               | Key Identifier                                        | KeyVrsn          | Mandatory         | Version of the cryptographic key                                                                                                                                                                                                                                                                                                                                                                             | Max140Text                |
| 4         | Sequence Number           | Key Identifier                                        | SeqNb            | Optional          | Number of usages of the cryptographic key.                                                                                                                                                                                                                                                                                                                                                                   | Number                    |
| 4         | Derivation Identification | Key Identifier                                        | DerivtnId        | Optional          | Identification used for derivation of a unique key from a master key provided for the data protection.                                                                                                                                                                                                                                                                                                       | Max500Binary              |
| 3         | MAC  Algorithm            | Authenticated Data                                    | MACAlgo          | Mandatory         | Algorithm to compute message authentication code (MAC).                                                                                                                                                                                                                                                                                                                                                      | AlgorithmIdentification22 |
| 4         | Algorithm                 | MAC  Algorithm                                        | Algo             | Mandatory         | Identification of the MAC algorithm.<br />Allowed values:<br />- `CCA1`: CMAC with AES128<br />- `CMA1`: SHA-256 CMAC with AES128<br />- `CM31`: SHA3-256 CMAC with AES128<br />- `CCA2`: CMAC with AES192<br />- `CMA9`: SHA-384 CMAC with AES192<br />- `CM32`: SHA3-384 CMAC with AES192<br />- `CCA3`: CMAC with AES256<br />- `CMA5`: SHA-512 CMAC with AES256<br />- `CM33`: SHA3-512 CMAC with AES256 | Algorithm17Code           |
| 4         | Parameter                 | MAC  Algorithm                                        | Param            | Optional          | Parameters associated to the MAC algorithm.                                                                                                                                                                                                                                                                                                                                                                  | Parameter7                |
| 5         | Initialisation Vector     | Parameter                                             | InitlstnVctr     | Optional          | Initialisation vector of a cipher block chaining (CBC) mode encryption.                                                                                                                                                                                                                                                                                                                                      | Max500Binary              |
| 5         | Byte Padding              | Parameter                                             | BPddg            | Optional          | Byte padding for a cypher block chaining mode encryption, if the padding is not implicit.                                                                                                                                                                                                                                                                                                                    | BytePadding1Code          |
| 3         | Encapsulated Content      | Authenticated Data                                    | NcpsltdCntt      | Mandatory         | Data to authenticate.                                                                                                                                                                                                                                                                                                                                                                                        | EncapsulatedContent3      |
| 4         | Content Type              | Encapsulated Content                                  | CnttTp           | Mandatory         | Type of data which have been authenticated.<br />Allowed values:<br />- `DATA` (plain data)                                                                                                                                                                                                                                                                                                                  |                           |
| 4         | Content                   | Encapsulated Content                                  | Cntt             | Optional          | Actual data to authenticate.<br />Format: Base64<br /><br />Restrictions:<br />- MinLength: 1<br />- MaxLength: 102400                                                                                                                                                                                                                                                                                       | Max100KBinary             |
| 3         | MAC                       | Authenticated Data                                    | MAC              | Mandatory         | Message authentication code value.<br />Format: Base64<br />Restrictions:<br />- MinLength: 1<br />- MaxLength: 140                                                                                                                                                                                                                                                                                          | Max140Binary              |

# MAC Generation

For further information on MAC generation for Nexo messages, please see the Nexo Protocol Security MUG section 5.

MAC generation and MAC verification use the same algorithms. MAC is verified by generating the MAC from the received message, and compared to the received MAC. In response messages, the gateway will generate a security trailer using the same MAC algorithm that was used in the request message.

MAC computation is carried out on the **message body only**. The header (and, obviously, security trailer) components of a message should not be included in the MAC computation input.

It is important that the MAC computation is carried out on the minified version of the message body, omitting all unnecessary spaces and carriage returns. This ensures that calculation and verification can be carried out using consistent representations of the message body.

## Supported MAC Algorithms

The Toro Gateway supports the following MAC algorithms:

- CMAC with AES128
- SHA-256 CMAC with AES128
- SHA3-256 CMAC with AES128
- CMAC with AES192
- SHA-384 CMAC with AES192
- SHA3-384 CMAC with AES192
- CMAC with AES256
- SHA-512 CMAC with AES256
- SHA3-512 CMAC with AES256

## MAC Generation Examples

The following examples are adapted from the Nexo Protocol Security MUG section 5.4.

As an example message body to compute a MAC example, we will use the `AcceptorDiagnosticRequest` message of the Acquirer protocol.

As input of the `AcceptorDiagnosticRequest` MAC, the XML encoded body DiagnosticRequest of the message is:

```xml
<DgnstcReq>
  <Envt>
    <AcqrrParamsVrsn>2010-01-01T08:00:00</AcqrrParamsVrsn>
    <MrchntId>
      <Id>EPASMER001</Id>
      <Tp>MERC</Tp>
    </MrchntId>
    <POIId>
      <Id>66000001</Id>
      <Tp>OPOI</Tp>
      <Issr>ACQR</Issr>
    </POIId>
  </Envt>
</DgnstcReq>
```

Once unnecessary spaces and carriage returns are removed, `AcceptorDiagnosticRequest` is:

:::CodeblockTabs
XML

```xml
<DgnstcReq><Envt><AcqrrParamsVrsn>2010-01-01T08:00:00</AcqrrParamsVrsn><MrchntId><Id>EPASMER001</Id><Tp>MERC</Tp></MrchntId><POIId><Id>66000001</Id><Tp>OPOI</Tp><Issr>ACQR</Issr></POIId></Envt></DgnstcReq>
```
:::

### CMAC examples with AES256

These examples demonstrate MAC calculation using CMAC AES-256. The examples are taken from the Nexo Protocol Security MUG.

In these examples, the following AES256 bit key is used:

`34790642 381CC5FF AD606931 49B29D39 340E5482 748C37EB 8A6F4BF3 F3EF39E2`

**Example: CMAC with AES256**

See Nexo Protocol Security MUG Section 5.4.6 for a full breakdown of the MAC generation process. Example commands using OpenSSL are shown below.

```bash
# Save the input message as message.txt
echo -n "<DgnstcReq><Envt><AcqrrParamsVrsn>2010-01-01T08:00:00</AcqrrParamsVrsn><MrchntId><Id>EPASMER001</Id><Tp>MERC</Tp></MrchntId><POIId><Id>66000001</Id><Tp>OPOI</Tp><Issr>ACQR</Issr></POIId></Envt></DgnstcReq>" > message.txt

# Save the key as hey.hex
echo -n "34790642381CC5FFAD60693149B29D39340E5482748C37EB8A6F4BF3F3EF39E2" > hey.hex

# Calculate the MAC using cipher AWS-256
openssl dgst -mac cmac -macopt cipher:aes-256-cbc -macopt hexkey:$(cat key.hex) message.txt

# Expected output:
# CMAC(message.txt)= f712286e727f3f2681d74101e0be8de3

# Convert the hex to base64
echo "f712286e727f3f2681d74101e0be8de3" | xxd -r -p | base64
# Base64 representation of the MAC: 9xIobnJ/PyaB10EB4L6N4w==
```

The MAC of the message is: `F7 12 28 6E 72 7F 3F 26 81 D7 41 01 E0 BE 8D E3`

The Base64 representation of the MAC is: `9xIobnJ/PyaB10EB4L6N4w==`

The resulting XML encoded structure is shown below:

```xml
<SctyTrlr>
	<CnttTp>AUTH</CnttTp>
	<AuthntcdData>
		<Rcpt>
			<KeyIdr>
			  <KeyId>SpecV1TestKey</KeyId>
			  <KeyVrsn>1</KeyVrsn>
			</KeyIdr>
		</Rcpt>
		<MACAlgo>
			<Algo>CCA3</Algo>
		</MACAlgo>
		<NcpsltdCntt>
			<CnttTp>DATA</CnttTp>
		</NcpsltdCntt>
		<MAC>9xIobnJ/PyaB10EB4L6N4w==</MAC>
	</AuthntcdData>
</SctyTrlr>
```

**Example: SHA-512 CMAC with AES256**

See section Nexo Protocol Security MUG Section 5.4.6.3 for a full breakdown of the MAC generation process. Example commands using OpenSSL are shown below.

```bash
# Generate a SHA-512 digest of the message and save it to digest.bin
echo -n "<DgnstcReq><Envt><AcqrrParamsVrsn>2010-01-01T08:00:00</AcqrrParamsVrsn><MrchntId><Id>EPASMER001</Id><Tp>MERC</Tp></MrchntId><POIId><Id>66000001</Id><Tp>OPOI</Tp><Issr>ACQR</Issr></POIId></Envt></DgnstcReq>" | openssl dgst -sha512 -binary > digest.bin

# Check it matches the expected value
xxd digest.bin
# 00000000: 09ae 273c ac0d ef0f 4243 e9dc 9dfc b076  ..'<....BC.....v
# 00000010: 5c7e b7ee a016 b5b2 8ae1 5406 5264 ce6a  \~........T.Rd.j
# 00000020: 2573 045d ee09 d8d7 1696 840a 70c8 2140  %s.]........p.!@
# 00000030: e4dc d52e 83f5 578e 9448 71b2 faef c117  ......W..Hq.....

# Save the key as hey.hex
echo -n "34790642381CC5FFAD60693149B29D39340E5482748C37EB8A6F4BF3F3EF39E2" > hey.hex

# Calculate the MAC using AES-256 cipher
openssl dgst -mac cmac -macopt cipher:aes-256-cbc -macopt hexkey:$(cat key.hex) digest.bin

# Expected output:
# CMAC(digest.bin)= 45a2bf16ea10fd137ea95eb8256ed92f

# Convert the hex to base64
echo "45a2bf16ea10fd137ea95eb8256ed92f" | xxd -r -p | base64
# Base64 representation of the MAC: RaK/FuoQ/RN+qV64JW7ZLw==
```

The resulting XML encoded structure is shown below:

```xml
<SctyTrlr>
	<CnttTp>AUTH</CnttTp>
	<AuthntcdData>
		<Rcpt>
			<KeyIdr>
				<KeyId>SpecV1TestKey</KeyId>
				<KeyVrsn>1</KeyVrsn>
			</KeyIdr>
		</Rcpt>
		<MACAlgo>
			<Algo>CMA5</Algo>
		</MACAlgo>
		<NcpsltdCntt>
			<CnttTp>DATA</CnttTp>
		</NcpsltdCntt>
		<MAC>RaK/FuoQ/RN+qV64JW7ZLw==</MAC>
	</AuthntcdData>
</SctyTrlr>
```

**Example: SHA3-512 CMAC with AES256**

See section Nexo Protocol Security MUG Section 5.4.6.4 for a full breakdown of the MAC generation process. Example commands using OpenSSL are shown below.

```bash
# Generate a SHA-512 digest of the message and save it to digest.bin
echo -n "<DgnstcReq><Envt><AcqrrParamsVrsn>2010-01-01T08:00:00</AcqrrParamsVrsn><MrchntId><Id>EPASMER001</Id><Tp>MERC</Tp></MrchntId><POIId><Id>66000001</Id><Tp>OPOI</Tp><Issr>ACQR</Issr></POIId></Envt></DgnstcReq>" | openssl dgst -sha3-512 -binary > digest.bin

# Check it matches the expected value
xxd digest.bin
# 00000000: 2b43 71a8 c795 0c12 9576 1200 eaec 3551  +Cq......v....5Q
# 00000010: 611b 1c50 8334 fc3c 5a39 78a5 57ec a37a  a..P.4.<Z9x.W..z
# 00000020: 45fc f5a2 a6e3 afc3 d728 2888 cb0d 7c74  E........((...|t
# 00000030: 5e6f 7daf 0944 5f9e 5043 d820 2e69 a99c  ^o}..D_.PC. .i..

# Save the key as hey.hex
echo -n "34790642381CC5FFAD60693149B29D39340E5482748C37EB8A6F4BF3F3EF39E2" > hey.hex

# Calculate the MAC using AES-256 cipher
openssl dgst -mac cmac -macopt cipher:aes-256-cbc -macopt hexkey:$(cat key.hex) digest.bin

# Expected output:
# CMAC(digest.bin)= ba35edff29f16bfe4ce7fc1bbf784aab

# Convert the hex to base64
echo "ba35edff29f16bfe4ce7fc1bbf784aab" | xxd -r -p | base64
# Base64 representation of the MAC: ujXt/ynxa/5M5/wbv3hKqw==
```

The resulting XML encoded structure is shown below:

```xml
<SctyTrlr>
	<CnttTp>AUTH</CnttTp>
	<AuthntcdData>
		<Rcpt>
			<KeyIdr>
				<KeyId>SpecV1TestKey</KeyId>
				<KeyVrsn>1</KeyVrsn>
			</KeyIdr>
		</Rcpt>
		<MACAlgo>
			<Algo>CM33</Algo>
		</MACAlgo>
		<NcpsltdCntt>
			<CnttTp>DATA</CnttTp>
		</NcpsltdCntt>
		<MAC>ujXt/ynxa/5M5/wbv3hKqw==</MAC>
	</AuthntcdData>
</SctyTrlr>
```



# Responses to common security trailer scenarios

- Messages received by the Gateway which do not include a security trailer will be rejected with a 400 BAD REQUEST error.
- Messages which include an invalid (e.g. incorrectly formatted) security trailer will be rejected with a 400 BAD REQUEST error.
- Messages whose security trailer cannot be verified against the sender's shared passphrase will be rejected with a 403 FORBIDDEN error.

