---
name: seal_aead
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: impure
signature: "func SealAEAD(key, plaintext, aad []byte) (nonce, ciphertext []byte, err error)"
description: "Cifra plaintext con ChaCha20-Poly1305 usando una clave simétrica de 32 bytes. Genera un nonce aleatorio por llamada. Admite datos autenticados adicionales (AAD) para vincular contexto al cifrado sin cifrarlo."
tags: [messaging, e2e-crypto, crypto, aead, chacha20poly1305, symmetric, e2e-messaging]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports:
  - crypto/rand
  - golang.org/x/crypto/chacha20poly1305
params:
  - name: key
    desc: "Clave simétrica de exactamente 32 bytes (256 bits). Típicamente la room key distribuida con SealKeyBox."
  - name: plaintext
    desc: "Bytes a cifrar. Puede ser vacío."
  - name: aad
    desc: "Datos autenticados adicionales (AAD): se autentican pero no se cifran. Útil para room ID, número de secuencia, etc. Puede ser nil."
output: "nonce (12 bytes aleatorios), ciphertext (plaintext cifrado + 16 bytes de tag Poly1305), o error si la clave tiene longitud incorrecta o falla el RNG."
tested: true
tests:
  - "round-trip con aad"
  - "round-trip sin aad (nil)"
  - "error con clave de longitud incorrecta"
  - "error de autenticacion con ciphertext modificado"
  - "error de autenticacion con aad distinto"
  - "nonces distintos en llamadas sucesivas"
test_file_path: "functions/cybersecurity/e2e_messaging_crypto_test.go"
file_path: "functions/cybersecurity/seal_aead.go"
---

## Ejemplo

```go
key := make([]byte, 32) // en producción: room key distribuida con SealKeyBox
aad := []byte("room:sala-general:seq:42")
nonce, ct, err := cybersecurity.SealAEAD(key, []byte("hola sala"), aad)
if err != nil {
    log.Fatal(err)
}
// Almacenar nonce junto al ciphertext para descifrar después
```

## Cuando usarla

Al cifrar cada mensaje en una sala del bus: usa la room key de la sala como `key`, incluye el ID de sala y número de secuencia en `aad` para prevenir replay attacks entre salas, y transmite `nonce + ciphertext` juntos al destinatario.

## Gotchas

- El nonce es aleatorio (12 bytes): con una misma key, la probabilidad de colisión de nonces es despreciable para <2^32 mensajes, pero en escenarios de alto volumen considera rotar la room key periódicamente.
- El ciphertext es 16 bytes más largo que el plaintext (tag Poly1305).
- `aad` no viaja cifrado: el destinatario debe reconstruirlo independientemente para verificar. Si aad difiere aunque sea 1 bit, OpenAEAD falla con error de autenticación.
- Nunca reutilizar `(key, nonce)` para dos plaintexts distintos: rompe la confidencialidad de ChaCha20.
