Qué significa “cifrado en reposo” en la práctica
“En reposo” incluye bases de datos, archivos en sistemas de ficheros, volúmenes/discos, snapshots y backups (incluyendo copias exportadas a almacenamiento de objetos). El objetivo operativo es reducir el impacto de pérdidas de soportes, accesos no autorizados al almacenamiento, fugas por copias fuera de banda y exposición accidental de dumps. En este capítulo nos enfocamos en decisiones de arquitectura: dónde cifrar (disco/volumen, motor de BD, aplicación), qué se gana y qué se pierde (búsqueda, indexación, rotación, control de acceso, exposición a administradores), y cómo diseñar backups cifrados con pruebas de restauración que validen integridad.
Tres niveles de cifrado en reposo (y cuándo elegir cada uno)
1) Cifrado a nivel de disco/volumen (FDE / volumen)
El cifrado de disco/volumen protege datos cuando el medio está apagado o fuera del sistema (robo de disco, snapshot copiado, acceso directo al bloque). Una vez montado y desbloqueado, el sistema operativo entrega datos en claro a procesos con permisos, por lo que no es una barrera fuerte contra usuarios privilegiados dentro del host.
- Ventajas: transparente para aplicaciones; no afecta consultas ni índices; cubre archivos temporales, swap, logs locales; despliegue rápido.
- Limitaciones: si el host está comprometido o un administrador tiene acceso al sistema en ejecución, puede leer datos; rotación de claves suele ser “por volumen” y no por registro/campo; control de acceso se basa en permisos del SO/infra.
- Casos típicos: VMs con discos cifrados, portátiles/estaciones, nodos de bases de datos donde el riesgo principal es exfiltración del almacenamiento.
2) Cifrado a nivel de base de datos (TDE / cifrado del motor)
El motor cifra páginas/segmentos en disco y descifra al leer. Protege contra acceso al almacenamiento subyacente (archivos de datos, snapshots, backups generados por el motor si están incluidos), manteniendo la semántica de consultas e índices porque el cifrado ocurre “debajo” del SQL.
- Ventajas: mínimo impacto en la aplicación; búsqueda e indexación funcionan normalmente; suele cubrir archivos de datos y, según configuración, logs/redo/undo.
- Limitaciones: un usuario con privilegios en la BD o acceso al proceso puede extraer datos en claro; no protege contra consultas legítimas abusivas; rotación depende del motor y puede ser costosa; no segmenta por tenant/campo.
- Casos típicos: bases de datos gestionadas donde se quiere protección “por defecto” en reposo sin rediseñar esquema.
3) Cifrado a nivel de aplicación (campo/registro)
La aplicación cifra valores sensibles antes de persistirlos (por ejemplo, columnas específicas o blobs). Es el enfoque que mejor reduce la exposición a administradores de infraestructura y, en ciertos diseños, a administradores de base de datos, porque la BD almacena ciphertext y la clave no reside en el motor.
- Ventajas: control fino por campo/registro/tenant; rotación selectiva; posibilidad de separar funciones (DBA no ve datos); útil para cumplir políticas internas de “need-to-know”.
- Limitaciones: búsqueda, ordenación e indexación se complican; requiere cambios de esquema y lógica; manejo de versiones de cifrado; riesgo de errores de implementación (serialización, AAD, nonces, migraciones).
- Casos típicos: PII/PHI, secretos de negocio, datos multi-tenant con requisitos de aislamiento, entornos con operadores/DBAs no confiables para ver datos.
Comparativa práctica: búsqueda, indexación, rotación, control de acceso y exposición a administradores
| Criterio | Disco/volumen | Base de datos (TDE) | Aplicación (campo/registro) |
|---|---|---|---|
| Búsqueda/consultas | Sin cambios | Sin cambios | Limitada; requiere diseño adicional |
| Indexación/ordenación | Sin cambios | Sin cambios | Difícil sobre ciphertext; suele usarse índice auxiliar |
| Rotación de claves | Por volumen; operativa infra | Depende del motor; puede ser pesada | Granular; requiere migraciones y versionado |
| Control de acceso | Permisos SO/infra | Roles/privilegios BD | En la app + control de claves |
| Exposición a admins | Admins del host pueden leer en ejecución | DBA/roles altos pueden leer | Reduce exposición si claves no están en BD |
| Backups | Depende: copia a nivel bloque puede ir cifrada; exportaciones pueden quedar en claro | Backups del motor pueden ir cifrados si se configura | Backups contienen ciphertext; aún conviene cifrar el backup |
Patrón común en producción: combinar cifrado de volumen (capa base) + cifrado del motor (si está disponible) + cifrado a nivel de aplicación para campos realmente sensibles. La combinación no sustituye controles de acceso, pero reduce el radio de impacto de fugas.
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
Guía de decisión rápida (sin repetir teoría)
Preguntas que fuerzan la elección
- ¿Necesitas filtrar/ordenar por el dato sensible? Si sí, evita cifrar ese campo sin un diseño de búsqueda; considera separar “dato para búsqueda” (tokenizado) del “dato completo” (cifrado).
- ¿El DBA/operador debe poder ver el dato? Si no, prioriza cifrado en aplicación con claves fuera de la BD.
- ¿Tu mayor riesgo es pérdida de snapshots/backups? Asegura cifrado del backup y control de acceso al storage; FDE/TDE ayudan, pero no cubren todos los flujos (exports, dumps, ETL).
- ¿Necesitas rotación frecuente por cumplimiento? Cifrado por campo/registro con versionado facilita rotación selectiva; TDE/volumen suele ser más “grueso”.
Selección típica por tipo de dato
- Datos no sensibles: FDE/TDE por defecto.
- PII/PHI (nombre, documento, dirección): cifrado por campo; para búsquedas, usar índices auxiliares (ver sección de etiquetado y búsqueda).
- Tokens/credenciales de terceros: cifrado por campo + controles estrictos de acceso + rotación y auditoría.
- Documentos/adjuntos: cifrado por objeto (blob) en aplicación o en capa de almacenamiento de objetos con claves por tenant.
Cifrado a nivel de aplicación: patrón recomendado con AEAD y AAD
Qué cifrar y cómo representarlo
Para columnas sensibles, almacena un “sobre” (envelope) con metadatos mínimos para descifrar y rotar: versión, identificador de clave (kid), nonce/iv, ciphertext y tag. Evita mezclar datos de control con datos de negocio sin un formato estable.
{ "v": 3, "kid": "prod-app-keys/tenant-42/v7", "alg": "AES-256-GCM", "nonce": "...", "ct": "...", "tag": "..."}En bases relacionales, esto suele ser una columna BYTEA/BLOB o JSONB (si tu política lo permite). En almacenamiento de objetos, puede ser metadata + cuerpo cifrado.
AEAD: recomendación operativa
- Usa un esquema AEAD estándar soportado por tu plataforma (por ejemplo, AES-GCM o ChaCha20-Poly1305) y mantén consistencia por servicio.
- Define un versionado del formato de ciphertext desde el día 1 (campo
v), para permitir migraciones y rotación sin downtime. - Registra el kid (identificador de clave) junto al ciphertext para descifrado determinista y rotación controlada.
AAD con metadatos: cómo atar el ciphertext al contexto
El AAD (Additional Authenticated Data) permite autenticar metadatos sin cifrarlos. Úsalo para evitar “copiar/pegar ciphertext” entre contextos (por ejemplo, mover un valor cifrado de un tenant a otro o de una tabla a otra). Recomendación: construir AAD canónico y estable, con campos que no cambien durante la vida del dato.
Ejemplo de AAD canónico (serialización estable):
aad = concat( "tenant=42|", "table=customers|", "column=tax_id|", "row_id=12345|", "schema_v=2" )- tenant: evita que un ciphertext válido en un tenant sea aceptado en otro.
- tabla/columna: evita reuso malicioso entre campos con semántica distinta.
- row_id (o identificador lógico): opcional; aumenta el acoplamiento (bueno para anti-replay), pero complica migraciones si cambia el id.
- schema_v: permite evolucionar el AAD sin romper descifrado (manteniendo compatibilidad por versión).
Regla práctica: si un metadato puede cambiar (por ejemplo, mover filas, renumerar ids), no lo incluyas o inclúyelo con una estrategia de migración clara.
Búsqueda e indexación con campos cifrados: patrones seguros de ingeniería
El cifrado por campo rompe la búsqueda directa. En lugar de “buscar dentro del ciphertext”, usa un campo auxiliar para indexación, y conserva el valor completo cifrado.
- Búsqueda exacta: guarda un “token de búsqueda” derivado del valor normalizado (por ejemplo, email en minúsculas y sin espacios) en una columna indexada. Ese token debe ser resistente a enumeración según tu modelo de riesgo; en la práctica, limita quién puede consultar y monitoriza abuso.
- Prefijos/like: evita si no es imprescindible; suele filtrar demasiada información. Considera rediseñar UX (búsqueda por campos no sensibles) o usar servicios especializados con controles.
- Ordenación/rangos: si necesitas rangos sobre datos sensibles (salarios, fechas), evalúa si realmente es necesario; a menudo se puede ordenar por un campo no sensible (por ejemplo, fecha de alta) y mostrar el dato sensible descifrado solo al final.
Importante: documenta qué consultas quedan prohibidas o limitadas por el cifrado por campo; esto evita que el equipo “desactive” cifrado por presión de producto.
Diseño de cifrado de backups: no asumir que “ya está cifrado”
Mapa de flujos de backup que suelen escapar
- Dumps lógicos (SQL export, CSV, parquet): pueden salir en claro aunque la BD use TDE.
- ETL/replicación: pipelines que leen en claro y escriben a data lakes.
- Snapshots a nivel almacenamiento: suelen estar cifrados si el volumen lo está, pero revisa copias cruzadas entre cuentas/proyectos.
- Backups de aplicaciones: directorios con adjuntos, colas, caches persistentes.
Patrón recomendado: cifrado del backup como capa independiente
Diseña el backup para que sea cifrado antes de salir del entorno de cómputo o, como mínimo, cifrado en el destino con controles estrictos. Incluso si ya tienes FDE/TDE, el cifrado del backup reduce el riesgo de errores de configuración y de exportaciones en claro.
- Unidad de cifrado: por archivo de backup (por ejemplo, cada dump) o por “chunk” (para streaming y reintentos).
- Metadatos: incluye
backup_id,env,service,timestamp,schema_v,kid. - Integridad: usa AEAD para que cualquier corrupción o manipulación falle al restaurar.
Gestión de claves por entorno (dev/staging/prod) aplicada a backups
Separa claves por entorno para evitar que un backup de producción pueda descifrarse en dev/staging. Además, separa por dominio cuando tenga sentido (por ejemplo, claves de backups distintas a claves de cifrado de campos) para limitar impacto de exposición.
- Nomenclatura:
backup/{env}/{service}yappdata/{env}/{service}. - Política de acceso: el rol de “backup writer” solo cifra y sube; el rol de “restore” solo se habilita bajo procedimiento (break-glass) y queda auditado.
- Rotación: planifica rotación por ventanas (por ejemplo, mensual) y conserva capacidad de descifrar backups antiguos mediante
kidy retención de claves según política.
Backups multi-tenant
Si un mismo backup contiene datos de múltiples tenants, considera cifrar por tenant (múltiples archivos o múltiples “streams” cifrados) para permitir restauraciones parciales y reducir exposición cruzada. Si esto no es viable, al menos autentica en AAD el tenant_set o el identificador del conjunto de tenants incluido.
Etiquetado de datos sensibles: convertir “sensibilidad” en decisiones automáticas
Qué etiquetar
- Clasificación: público/interno/confidencial/restringido.
- Tipo: PII, credencial, financiero, salud, secreto comercial.
- Requisitos: “cifrar por campo”, “no exportar”, “retención 30 días”, “no indexar”.
Dónde vive el etiquetado
- Esquema: comentarios/metadata de columnas y tablas (cuando el motor lo soporte).
- Capa de aplicación: anotaciones en modelos/ORM para forzar cifrado, redacción en logs y políticas de exportación.
- Catálogo de datos: para gobernanza y auditoría (sin depender de memoria tribal).
Objetivo práctico: que el pipeline de backups y exports pueda leer etiquetas y aplicar reglas (por ejemplo, “si contiene restringido, cifrar siempre y bloquear exportación a destinos no aprobados”).
Procedimiento paso a paso: implementar cifrado por campo con rotación y AAD
Paso 1: inventario mínimo y selección de campos
- Lista tablas/colecciones y marca campos sensibles con etiqueta y justificación.
- Define qué operaciones necesitas: lectura, escritura, búsqueda exacta, auditoría.
Paso 2: define formato de ciphertext versionado
- Elige representación (
BLOBoJSON). - Incluye
v,kid,nonce,ct,tag. - Define cómo serializar AAD (canónico, estable).
Paso 3: implementa cifrado/descifrado en un módulo único
- Una librería interna por lenguaje para evitar divergencias.
- Interfaz:
encrypt(plaintext, aad, kid)ydecrypt(envelope, aad). - Registra métricas: tasa de fallos de autenticación, versión de ciphertext, latencia.
Paso 4: migración de datos
- Backfill por lotes: leer en claro, cifrar, escribir en nueva columna, validar, luego cortar.
- Compatibilidad temporal: lectura soporta claro y cifrado durante la transición (con fecha de retirada).
- Evita reescrituras innecesarias para no disparar costos de I/O y replicación.
Paso 5: rotación
- Define “clave activa” para nuevos writes y conserva claves antiguas para reads.
- Re-cifra gradualmente: job que reescribe registros con
kidantiguo akidnuevo. - Usa
vykidpara saber qué migrar, sin heurísticas.
Paso 6: pruebas que deben existir
- Prueba de AAD: si cambias
tenantotableen AAD, el descifrado debe fallar. - Prueba de corrupción: modificar 1 byte del ciphertext debe fallar.
- Prueba de versionado: descifrar
v=1,v=2,v=3con rutas explícitas. - Prueba de rotación: datos antiguos siguen legibles; nuevos datos usan
kidnuevo.
Pruebas de restauración de backups que validen integridad (no solo “arranca”)
Qué validar en una restauración real
- Integridad criptográfica: los backups cifrados deben fallar si se alteran; la restauración debe verificar autenticidad (AEAD) antes de importar.
- Integridad lógica: conteos, checksums de tablas críticas, consistencia referencial (según motor).
- Capacidad de descifrado: para datos cifrados por campo, ejecutar un conjunto de consultas de smoke test que descifren registros reales por tenant.
- Separación por entorno: un backup de prod no debe poder descifrarse con claves de staging/dev.
Checklist paso a paso para un “restore drill”
Selecciona un backup (incluye al menos uno antiguo para probar retención de claves).
Restaura en un entorno aislado con red restringida y credenciales temporales.
Verifica autenticidad del backup: descifrar/verificar AEAD antes de descomprimir/importar.
Importa y valida: conteos, checksums, consultas de negocio críticas.
Valida descifrado por campo: prueba por tenant, tabla y versión de esquema; fuerza fallos con AAD incorrecto para confirmar que el acoplamiento funciona.
Registra evidencias: tiempos, fallos, versiones de
kid, y acciones correctivas.
Errores comunes y cómo evitarlos
“Tenemos TDE, así que los dumps están cifrados”
Los dumps lógicos suelen salir en claro. Solución: cifrar el artefacto de backup/export como capa independiente y bloquear exports no cifrados por política y CI/CD.
“Ciframos por campo y luego necesitamos buscar por LIKE”
Solución: rediseñar requisitos; si la búsqueda es imprescindible, crear un índice auxiliar con tokenización y controles de acceso, y documentar el riesgo de enumeración.
“Rotamos claves pero no sabemos qué está cifrado con cuál”
Solución: persistir kid con cada ciphertext y mantener un job de migración que reporte progreso y rezagados.
“El DBA no debería ver datos, pero la app descifra en la BD”
Solución: descifrar en la aplicación (o en un servicio de dominio) y evitar funciones/UDAs en el motor que requieran claves dentro de la BD.
Referencias prácticas para aprender y practicar (sin historia)
- OWASP (cheatsheets de almacenamiento seguro y prácticas de ingeniería).
- Documentación de tu motor de base de datos sobre TDE, backups cifrados y gestión de claves (por ejemplo, guías oficiales de PostgreSQL/MySQL/SQL Server/Oracle o servicios gestionados equivalentes).
- Plataformas de aprendizaje con laboratorios de seguridad en la nube para practicar restauraciones y controles de acceso (por ejemplo, A Cloud Guru / Pluralsight, Coursera, Udemy) enfocadas en operaciones seguras.