# Envelope Encryption

Fuente conceptual: OpenViking `openviking/crypto/encryptor.py` (AGPL-3.0)
Reimplementar desde cero. No copiar codigo.

## Funciones a implementar

### 1. envelope_encrypt

- **Dominio:** cybersecurity
- **Lang:** Python
- **Purity:** impure (genera random bytes)
- **Signature:** `envelope_encrypt(plaintext: bytes, master_key: bytes) -> bytes`
- **Descripcion:** Cifra datos usando patron Envelope Encryption. Genera una clave de archivo aleatoria (file key), cifra los datos con AES-256-GCM usando la file key, luego cifra la file key con la master key.
- **Algoritmo:**
  1. Generar file_key aleatorio de 32 bytes
  2. Generar data_iv de 12 bytes
  3. Cifrar plaintext: `AES-GCM(file_key, data_iv, plaintext)` → encrypted_content
  4. Generar key_iv de 12 bytes
  5. Cifrar file_key: `AES-GCM(master_key, key_iv, file_key)` → encrypted_file_key
  6. Construir envelope: magic + version + lengths + encrypted_file_key + key_iv + data_iv + encrypted_content
- **Formato del envelope:**
  ```
  Magic    (4B): b"OVE1" (identificador)
  Version  (1B): 0x01
  Reserved (1B): 0x00
  EFK_len  (2B): big-endian, longitud de encrypted_file_key
  KIV_len  (2B): big-endian, longitud de key_iv
  DIV_len  (2B): big-endian, longitud de data_iv
  --- header: 12 bytes total ---
  Encrypted File Key (variable)
  Key IV (variable)
  Data IV (variable)
  Encrypted Content (variable, incluye GCM auth tag)
  ```
- **Deps:** `cryptography` (AESGCM), `secrets`, `struct`
- **Error type:** Exception
- **Tests:** encrypt → decrypt roundtrip, datos vacios, datos grandes

### 2. envelope_decrypt

- **Dominio:** cybersecurity
- **Lang:** Python
- **Purity:** impure (puede fallar en autenticacion)
- **Signature:** `envelope_decrypt(ciphertext: bytes, master_key: bytes) -> bytes`
- **Descripcion:** Descifra datos cifrados con envelope_encrypt.
- **Algoritmo:**
  1. Verificar magic bytes `b"OVE1"` al inicio — si no coincide, retornar datos sin cambiar (archivo no cifrado)
  2. Parsear header: version, lengths
  3. Extraer: encrypted_file_key, key_iv, data_iv, encrypted_content
  4. Descifrar file_key: `AES-GCM_decrypt(master_key, key_iv, encrypted_file_key)`
  5. Descifrar contenido: `AES-GCM_decrypt(file_key, data_iv, encrypted_content)`
- **Comportamiento especial:** Si ciphertext no empieza con magic, se asume que no esta cifrado y se retorna tal cual. Esto permite usar decrypt en archivos que pueden o no estar cifrados.
- **Deps:** `cryptography`, `struct`
- **Error type:** ValueError (envelope corrupto), AuthenticationError (key incorrecta)
- **Tests:** decrypt de datos cifrados, decrypt de datos no cifrados (passthrough), key incorrecta, envelope truncado, envelope con magic invalido

### 3. build_envelope / parse_envelope (helpers)

Pueden ser funciones internas puras usadas por encrypt/decrypt para construir y parsear el formato binario del envelope.
