Table of Contents

πŸ” XChaCha20-Poly1305

The XChaCha20Poly1305 API in LibSodium.Net provides authenticated encryption with associated data (AEAD) and extended nonce support (192-bit), making it safer for use in systems where nonce reuse is a concern. It supports both combined and detached encryption modes, and allows manual or automatic nonce handling through a unified API.

πŸ§‚ Based on libsodium's XChaCha20-Poly1305 construction
ℹ️ See also: API Reference for XChaCha20Poly1305


🌟 Features

  • Authenticated encryption with associated data (AEAD).
  • 24-byte nonce (192-bit) minimizes risk of nonce reuse.
  • Combined and detached mode support through a single API.
  • Optional additionalData for protocol-level authentication.
  • Manual or automatic nonce handling.
  • Span<T>-based API for high performance and low allocations.

✨ Encrypting and Decrypting Messages

Use the Encrypt and Decrypt methods to perform authenticated encryption. The mode is determined by the presence of the optional mac parameter.

πŸ“‹ Combined Mode (Auto Nonce, No AAD)

Span<byte> key = stackalloc byte[XChaCha20Poly1305.KeyLen];
RandomGenerator.Fill(key);

var plaintext = Encoding.UTF8.GetBytes("Auto nonce test");
Span<byte> ciphertext = stackalloc byte[plaintext.Length + XChaCha20Poly1305.MacLen + XChaCha20Poly1305.NonceLen];

XChaCha20Poly1305.Encrypt(ciphertext, plaintext, key);

Span<byte> decrypted = stackalloc byte[plaintext.Length];
XChaCha20Poly1305.Decrypt(decrypted, ciphertext, key);
Console.WriteLine(Encoding.UTF8.GetString(decrypted));

πŸ“‹ Combined Mode (Manual Nonce with AAD)

Span<byte> key = stackalloc byte[XChaCha20Poly1305.KeyLen];
Span<byte> nonce = stackalloc byte[XChaCha20Poly1305.NonceLen];
RandomGenerator.Fill(key);
RandomGenerator.Fill(nonce);

var plaintext = Encoding.UTF8.GetBytes("With AAD and nonce");
Span<byte> ciphertext = stackalloc byte[plaintext.Length + XChaCha20Poly1305.MacLen];
Span<byte> aad = Encoding.UTF8.GetBytes("metadata");

XChaCha20Poly1305.Encrypt(ciphertext, plaintext, key, aad: aad, nonce: nonce);

Span<byte> decrypted = stackalloc byte[plaintext.Length];
XChaCha20Poly1305.Decrypt(decrypted, ciphertext, key, aad: aad, nonce: nonce);
Console.WriteLine(Encoding.UTF8.GetString(decrypted));

πŸ“‹ Detached Mode (Manual Nonce)

Span<byte> key = stackalloc byte[XChaCha20Poly1305.KeyLen];
Span<byte> nonce = stackalloc byte[XChaCha20Poly1305.NonceLen];
RandomGenerator.Fill(key);
RandomGenerator.Fill(nonce);

var plaintext = Encoding.UTF8.GetBytes("Detached encryption");
Span<byte> ciphertext = stackalloc byte[plaintext.Length];
Span<byte> mac = stackalloc byte[XChaCha20Poly1305.MacLen];

XChaCha20Poly1305.Encrypt(ciphertext, plaintext, key, mac, nonce: nonce);

Span<byte> decrypted = stackalloc byte[plaintext.Length];
XChaCha20Poly1305.Decrypt(decrypted, ciphertext, key, mac, nonce: nonce);
Console.WriteLine(Encoding.UTF8.GetString(decrypted));

⚠️ Error Handling

  • ArgumentException β€” invalid input sizes.
  • LibSodiumException β€” authentication failed (tampered data).

πŸ“ Notes

  • Nonce must be exactly 24 bytes.
  • Auto-nonce is prepended to ciphertext for easy reuse.
  • Buffers must have space for output (e.g., ciphertext includes MAC and possibly nonce). It can be longer than needed.
  • Encrypt and Decrypt automatically choose combined or detached mode depending on the presence of the mac parameter.
  • Use RandomGenerator.Fill() to safely generate keys and nonces.
  • AAD is optional but recommended for additional authentication context.

πŸ‘€ See Also