AEAD and Envelope

Read time 3 minutes Package: Nalix.Codec / Nalix.Network
On this page

Namespaces: Nalix.Codec.Security, Nalix.Codec.Security.Aead, Nalix.Codec.Security.Symmetric, Nalix.Codec.Security.Engine
Assembly: Nalix.Codec

This page covers the encryption primitives that matter most to transport and packet protection.

Source mapping

  • src/Nalix.Codec/Security/Aead/ChaCha20Poly1305.cs
  • src/Nalix.Codec/Security/Aead/Salsa20Poly1305.cs
  • src/Nalix.Codec/Security/Engine/AeadEngine.cs
  • src/Nalix.Codec/Security/Engine/SymmetricEngine.cs
  • src/Nalix.Codec/Security/Symmetric/ChaCha20.cs
  • src/Nalix.Codec/Security/Symmetric/Salsa20.cs
  • src/Nalix.Codec/Security/EnvelopeCipher.cs

Main types

  • ChaCha20Poly1305
  • Salsa20Poly1305
  • EnvelopeCipher

AEAD primitives

ChaCha20Poly1305 and Salsa20Poly1305 are detached-tag implementations.

They currently:

  • take spans first, with minimal-allocation overloads
  • authenticate AAD || pad16 || ciphertext || pad16 || lengths
  • verify the tag before returning decrypted data
  • bind the Nalix envelope header || nonce || userAAD into AEAD authentication, so tampering with sequence/header fields is rejected during decrypt

Size rules from source

TypeKey sizeNonce sizeTag size
ChaCha20Poly1305321216
Salsa20Poly130516 or 32816

EnvelopeCipher

EnvelopeCipher is the high-level encryption facade used by transport-facing code.

It dispatches by CipherSuiteType and hides whether the selected suite is:

  • AEAD: header || nonce || ciphertext || tag
  • stream/symmetric: header || nonce || ciphertext

Basic usage

Span<byte> ciphertext = stackalloc byte[plaintext.Length + EnvelopeCipher.HeaderSize + 32];

EnvelopeCipher.Encrypt(
    key,
    plaintext,
    ciphertext,
    aad,
    seq: null,
    algorithm: CipherSuiteType.Chacha20Poly1305,
    out int written);

Encryption & Decryption APIs

EnvelopeCipher exposes both 6-parameter (no explicit AAD) and 7-parameter (with ReadOnlySpan<byte> aad) overloads for Encrypt, Decrypt, and TryDecrypt:

Encryption API

public static void Encrypt(
    ReadOnlySpan<byte> key,
    ReadOnlySpan<byte> plaintext,
    Span<byte> ciphertext,
    uint? seq,
    CipherSuiteType algorithm,
    out int written);

public static void Encrypt(
    ReadOnlySpan<byte> key,
    ReadOnlySpan<byte> plaintext,
    Span<byte> ciphertext,
    ReadOnlySpan<byte> aad,
    uint? seq,
    CipherSuiteType algorithm,
    out int written);

Throwing Decryption API

public static void Decrypt(
    ReadOnlySpan<byte> key,
    ReadOnlySpan<byte> envelope,
    Span<byte> plaintext,
    CipherSuiteType expectedAlgorithm,
    out int written, out uint seq);

public static void Decrypt(
    ReadOnlySpan<byte> key,
    ReadOnlySpan<byte> envelope,
    Span<byte> plaintext,
    ReadOnlySpan<byte> aad,
    CipherSuiteType expectedAlgorithm,
    out int written, out uint seq);

Throws CipherException on parse failure, algorithm mismatch, or authentication failure. Throws ArgumentException if the destination plaintext buffer is too small.

Decrypt delegates internally to TryDecrypt and translates CipherError into exceptions.

Non-throwing Decryption API

public static bool TryDecrypt(
    ReadOnlySpan<byte> key,
    ReadOnlySpan<byte> envelope,
    Span<byte> plaintext,
    CipherSuiteType expectedAlgorithm,
    out int written, out uint seq);

public static bool TryDecrypt(
    ReadOnlySpan<byte> key,
    ReadOnlySpan<byte> envelope,
    Span<byte> plaintext,
    ReadOnlySpan<byte> aad,
    CipherSuiteType expectedAlgorithm,
    out int written, out uint seq);

Returns false on any failure. Does not throw on authentication or formatting failures.

CipherError values

The internal CipherError enum distinguishes the following failure modes:

ValueMeaning
EnvelopeTooShortThe envelope buffer is too short to contain a valid header.
InvalidHeaderThe envelope header magic or version is invalid.
InvalidNonceLengthThe declared nonce length does not match the expected size for the cipher suite.
CiphertextTooShortThe ciphertext portion is shorter than the declared tag or minimum size.
InvalidTagLengthThe authentication tag length is invalid for the cipher suite.
AlgorithmMismatchThe algorithm declared in the envelope does not match expectedAlgorithm.
AuthenticationFailedAEAD tag verification failed.
UnsupportedAlgorithmThe cipher suite is not recognized.
DestinationTooSmallThe plaintext output buffer is too small for the decrypted payload.

Current runtime behavior

  • GetNonceLength(...) and GetTagLength(...) expose suite-dependent sizing
  • GetNonceLength(...) and GetTagLength(...) throw CipherException for unsupported cipher suites
  • AEAD suites route into AeadEngine
  • non-AEAD suites route into SymmetricEngine
  • AEAD encryption generates a fresh random nonce internally per call
  • AEAD decryption treats envelope header mutations such as sequence-number changes as authentication failures
  • Envelope parsing uses EnvelopeFormat.TryParseEnvelope() internally; the throwing ParseEnvelope() is also available but TryParseEnvelope is the primary path