Principios de diseño de seguridad: el marco CIAAN

Objetivos: Al terminar este tema, podrás…

  • Aplicar los cinco principios fundamentales como criterios de diseño de sistemas seguros
  • Seleccionar controles técnicos apropiados para proteger cada principio
  • Evaluar arquitecturas de seguridad según su cobertura de los principios CIAAN
  • Identificar compromisos (trade-offs) entre principios en decisiones de diseño

El marco CIAAN como herramienta de ingeniería

En temas anteriores analizamos amenazas y actores. Ahora respondemos la pregunta central del diseño de seguridad: ¿qué propiedades debe garantizar un sistema seguro?

El marco CIAAN define cinco propiedades fundamentales que todo sistema debe proteger:

PrincipioPregunta de diseño
Confidencialidad¿Quién puede acceder a esta información?
Integridad¿Cómo garantizo que los datos no fueron alterados?
Autenticación¿Cómo verifico la identidad de usuarios y sistemas?
Availability (Disponibilidad)¿Cómo garantizo acceso cuando se necesita?
No repudio¿Cómo pruebo quién realizó cada acción?

Como ingeniero, usarás estos principios para:

  1. Definir requisitos de seguridad — Cada activo necesita protección de uno o más principios
  2. Seleccionar controles técnicos — Cada control protege principios específicos
  3. Evaluar arquitecturas — Un sistema bien diseñado cubre los cinco principios
  4. Justificar decisiones — “Implementamos X para proteger Y”

Los cinco principios en profundidad

1. Confidencialidad

Definición técnica: Propiedad que garantiza que la información solo es accesible para entidades autorizadas.

Pregunta de diseño: ¿Quién debe poder leer esta información, y cómo evito que otros la vean?

Controles técnicos

ControlAplicaciónConsideraciones de implementación
Cifrado en reposoDatos almacenadosAES-256 para bases de datos, discos completos
Cifrado en tránsitoComunicacionesTLS 1.3, certificados válidos
Control de accesoAutorizaciónRBAC, listas de control de acceso
Clasificación de datosPolíticaEtiquetado por sensibilidad (público, interno, confidencial, secreto)
TokenizaciónDatos sensiblesReemplazar PII con tokens no reversibles

Decisiones de diseño

  • ¿Dónde almacenar claves? — Hardware Security Modules (HSM), servicios de gestión de secretos (Vault, AWS KMS)
  • ¿Qué algoritmos usar? — Preferir estándares actuales (AES-256, RSA-4096, Curve25519)
  • ¿Cifrar todo o solo datos sensibles? — Balance entre rendimiento y seguridad

Caso de ingeniería: Sistema de salud

Requisito: Los historiales médicos solo deben ser accesibles por el paciente y médicos autorizados.

Diseño:

1. Cifrado de datos en reposo (AES-256)
2. Cifrado en tránsito (TLS 1.3)
3. Control de acceso basado en roles (médico, paciente, administrador)
4. Logs de acceso para auditoría
5. Segregación de datos por paciente

2. Integridad

Definición técnica: Propiedad que garantiza que la información no ha sido modificada, eliminada o creada sin autorización.

Pregunta de diseño: ¿Cómo detecto si alguien alteró estos datos?

Controles técnicos

ControlAplicaciónConsideraciones de implementación
Hashes criptográficosVerificación de archivosSHA-256, SHA-3
Firmas digitalesAutenticación de origenRSA, ECDSA
HMACMensajes autenticadosCombina hash con clave secreta
Validación de entradaAplicaciones webSanitización, prepared statements
Control de versionesArchivos y códigoGit, sistemas de auditoría

Decisiones de diseño

  • ¿Validar en cliente o servidor? — Siempre en servidor (nunca confiar en el cliente)
  • ¿Qué constituye una modificación válida? — Definir reglas de negocio claras
  • ¿Cómo manejar conflictos de versiones? — Estrategias de merge, locks optimistas

Caso de ingeniería: Sistema bancario

Requisito: Una transferencia de 10.000.000 en tránsito.

Diseño:

1. Firma digital del cliente sobre la transacción
2. TLS con certificate pinning
3. Validación de montos contra límites de cuenta
4. Hash de la transacción almacenado para verificación
5. Reconciliación automática de transacciones

3. Disponibilidad (Availability)

Definición técnica: Propiedad que garantiza que sistemas y datos estén accesibles para usuarios autorizados cuando los necesiten.

Pregunta de diseño: ¿Cómo garantizo que el sistema funcione bajo condiciones adversas?

Controles técnicos

ControlAplicaciónConsideraciones de implementación
RedundanciaServidores y datosClusters, replicación, múltiples zonas
Balanceo de cargaDistribución de tráficoHAProxy, nginx, load balancers en nube
BackupsRecuperación de datos3-2-1 (3 copias, 2 medios, 1 offsite)
CDNContenido estáticoDistribución geográfica, caché
Rate limitingProtección DoSLímites por IP, por usuario, por API key
Circuit breakersResilienciaFallar rápido, degradación graceful

Métricas de disponibilidad

SLADowntime anualDowntime mensual
99%3.65 días7.3 horas
99.9%8.76 horas43.8 minutos
99.99%52.6 minutos4.38 minutos
99.999%5.26 minutos26.3 segundos

Caso de ingeniería: Portal de inscripciones

Requisito: El portal debe soportar 10,000 usuarios concurrentes sin degradación durante el período de inscripciones.

Diseño:

1. Arquitectura auto-escalable (Kubernetes, AWS Auto Scaling)
2. Base de datos replicada con read replicas
3. CDN para contenido estático
4. Cola de mensajes para operaciones pesadas
5. Rate limiting por usuario (máx 10 requests/segundo)
6. Plan de capacidad con pruebas de carga previas

4. Autenticación

Definición técnica: Proceso de verificar que una entidad (usuario, dispositivo, sistema) es quien afirma ser.

Pregunta de diseño: ¿Cómo verifico la identidad antes de conceder acceso?

Factores de autenticación

FactorTipoEjemplosFortaleza
ConocimientoAlgo que sabesContraseña, PIN, respuesta secretaBaja (phisheable)
PosesiónAlgo que tienesTeléfono, hardware token, smart cardMedia
InherenciaAlgo que eresHuella, rostro, iris, vozAlta (no transferible)
UbicaciónDonde estásIP, geolocalización, redComplementario
ComportamientoCómo actúasPatrones de escritura, usoComplementario

Arquitecturas de autenticación

PatrónUsoConsideraciones
Autenticación localSistemas internosAlmacenamiento seguro de credenciales (bcrypt, Argon2)
SSO (Single Sign-On)Múltiples aplicacionesSAML, OIDC, reducción de superficie de ataque
OAuth 2.0 / OIDCAPIs y aplicaciones modernasTokens de acceso, refresh tokens
Certificados X.509Sistemas y serviciosmTLS, autenticación de máquina a máquina

Caso de ingeniería: Aplicación bancaria móvil

Requisito: Autenticación fuerte que balance seguridad y usabilidad.

Diseño:

1. Registro con verificación de identidad (KYC)
2. Autenticación primaria: biometría (huella/rostro)
3. Fallback: PIN de 6 dígitos
4. MFA obligatorio para operaciones sensibles
5. Límite de intentos fallidos (bloqueo temporal)
6. Device binding (vincular a dispositivo específico)
7. Notificaciones de acceso desde nuevos dispositivos

5. No repudio

Definición técnica: Propiedad que impide que una entidad niegue haber realizado una acción que efectivamente realizó.

Pregunta de diseño: ¿Cómo pruebo quién hizo qué y cuándo?

Controles técnicos

ControlAplicaciónConsideraciones de implementación
Firmas digitalesDocumentos y transaccionesPKI, certificados de usuario
Logs de auditoríaTodas las accionesInmutables, con timestamp verificable
TimestampingPrueba temporalAutoridades de tiempo certificadas (TSA)
BlockchainRegistros distribuidosInmutabilidad por consenso
Notarización digitalDocumentos legalesServicios de firma electrónica certificada

Requisitos para no repudio efectivo

  1. Autenticación fuerte — Saber quién realizó la acción
  2. Logs inmutables — No poder alterar el registro después del hecho
  3. Timestamp verificable — Probar cuándo ocurrió
  4. Integridad del registro — El log mismo no puede ser modificado

Caso de ingeniería: Sistema de votación electrónica

Requisito: Cada voto debe ser verificable, pero el votante debe permanecer anónimo.

Diseño:

1. Autenticación fuerte del votante (identidad verificada)
2. Separación criptográfica entre identidad y voto
3. Recibo verificable para el votante
4. Log inmutable de votos (sin identidad)
5. Auditoría pública del conteo
6. Pruebas de conocimiento cero para verificación

Concesiones entre principios

En la práctica, los principios pueden entrar en conflicto. Como ingeniero, debes balancear:

Confidencialidad vs. Disponibilidad

Más confidencialidadMás disponibilidad
Cifrado de todoDatos en texto claro para rapidez
Acceso restrictivoAcceso amplio para productividad
Múltiples factores de autenticaciónAutenticación simple

Ejemplo: Un sistema de emergencias médicas debe priorizar disponibilidad sobre confidencialidad estricta en situaciones de vida o muerte.

Integridad vs. Rendimiento

Más integridadMás rendimiento
Verificación de cada operaciónVerificación por muestreo
Transacciones ACID completasEventual consistency
Validación exhaustivaValidación mínima

Ejemplo: Un sistema de trading de alta frecuencia puede tolerar eventual consistency a cambio de latencia mínima.

No repudio vs. Privacidad

Más no repudioMás privacidad
Logs detallados de toda actividadLogs mínimos
Identificación completaAnonimato
Retención prolongadaEliminación rápida

Ejemplo: El GDPR requiere minimizar datos retenidos, lo que puede conflictuar con requisitos de auditoría.


Evaluación de arquitecturas con CIAAN

Usa esta matriz para evaluar cobertura de seguridad:

ComponenteCIAANControles implementados
API GatewayTLS, rate limiting, auth, logs
Base de datos--Cifrado, backups, validación
Almacenamiento de archivos--Cifrado, checksums, redundancia
Sistema de autenticaciónMFA, logs, disponibilidad

Conceptos clave

TérminoDefinición
CIAANMarco de cinco principios fundamentales de seguridad
ConfidencialidadInformación accesible solo para entidades autorizadas
IntegridadInformación no alterada sin autorización
DisponibilidadSistemas accesibles cuando se necesitan
AutenticaciónVerificación de identidad de entidades
No repudioImposibilidad de negar acciones realizadas
MFAAutenticación que combina múltiples factores
SLAAcuerdo de nivel de servicio con garantías de disponibilidad
PKIInfraestructura de clave pública para firmas y cifrado

Ponte a prueba

  1. Diseño de controles: Una startup de fintech almacena datos financieros de clientes. Diseña controles técnicos para proteger cada uno de los cinco principios CIAAN. Justifica cada decisión.

  2. Análisis de trade-offs: Un hospital necesita un sistema de historiales médicos. ¿Cómo balancearías confidencialidad (proteger datos del paciente) con disponibilidad (acceso en emergencias)? Propón una arquitectura.

  3. Evaluación de arquitectura: Analiza un sistema que conoces (red social, banco, universidad) y evalúa qué principios están bien protegidos y cuáles podrían mejorarse.

  4. Caso de falla: El incidente de Equifax (2017) expuso datos de 147 millones de personas. ¿Qué principios CIAAN fallaron? ¿Qué controles habrían prevenido o mitigado el incidente?


Laboratorio práctico: Fundamentos de criptografía aplicada

Tiempo estimado: 120 minutos Requisitos: Python 3.8+, pip Instalación: pip install cryptography

Objetivo

Implementar los mecanismos criptográficos fundamentales que protegen confidencialidad, integridad y no repudio.

Parte 1: Hashing para integridad (20 min)

Los hashes permiten verificar que un archivo no ha sido modificado.

import hashlib
 
def calcular_hash(archivo: str) -> str:
    """Calcula el hash SHA-256 de un archivo."""
    sha256 = hashlib.sha256()
    with open(archivo, 'rb') as f:
        for bloque in iter(lambda: f.read(4096), b''):
            sha256.update(bloque)
    return sha256.hexdigest()
 
# Ejercicio 1.1: Calcula el hash de un archivo
hash_original = calcular_hash('documento.pdf')
print(f"Hash original: {hash_original}")
 
# Ejercicio 1.2: Modifica el archivo (añade un espacio) y recalcula
# ¿Qué observas sobre el nuevo hash?

Experimenta:

  1. Crea un archivo de texto y calcula su hash
  2. Modifica un solo carácter y recalcula
  3. ¿Qué porcentaje del hash cambió? ¿Por qué es importante esta propiedad?

Parte 2: Almacenamiento seguro de contraseñas (25 min)

Las contraseñas nunca se almacenan en texto plano. Usamos funciones de derivación de clave (KDF).

import os
import hashlib
 
def hash_password_inseguro(password: str) -> str:
    """MAL: Nunca usar MD5 para contraseñas."""
    return hashlib.md5(password.encode()).hexdigest()
 
def hash_password_seguro(password: str) -> tuple[bytes, bytes]:
    """BIEN: Usar salt aleatorio + función lenta."""
    salt = os.urandom(16)
    hash_resultado = hashlib.pbkdf2_hmac(
        'sha256',
        password.encode(),
        salt,
        iterations=100000  # Intencionalmente lento
    )
    return salt, hash_resultado
 
def verificar_password(password: str, salt: bytes, hash_guardado: bytes) -> bool:
    """Verifica si la contraseña coincide."""
    hash_intento = hashlib.pbkdf2_hmac(
        'sha256',
        password.encode(),
        salt,
        iterations=100000
    )
    return hash_intento == hash_guardado
 
# Ejercicio 2.1: Almacena y verifica una contraseña
salt, hash_pwd = hash_password_seguro("MiContraseña123!")
print(f"Salt: {salt.hex()}")
print(f"Hash: {hash_pwd.hex()}")
 
# Ejercicio 2.2: Verifica contraseña correcta e incorrecta
print(verificar_password("MiContraseña123!", salt, hash_pwd))  # True
print(verificar_password("ContraseñaIncorrecta", salt, hash_pwd))  # False

Experimenta:

  1. ¿Por qué usamos un salt aleatorio para cada usuario?
  2. ¿Qué pasaría si usamos 10 iteraciones en lugar de 100,000?
  3. Investiga: ¿Por qué se recomienda Argon2 o bcrypt sobre PBKDF2?

Parte 3: Cifrado simétrico para confidencialidad (30 min)

AES-256 protege datos en reposo y en tránsito.

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
 
def cifrar_aes(datos: bytes, clave: bytes) -> tuple[bytes, bytes]:
    """Cifra datos con AES-256-CBC."""
    iv = os.urandom(16)  # Vector de inicialización único
    cipher = Cipher(algorithms.AES(clave), modes.CBC(iv), backend=default_backend())
    encryptor = cipher.encryptor()
 
    # Padding PKCS7 (AES requiere bloques de 16 bytes)
    padding_length = 16 - (len(datos) % 16)
    datos_padded = datos + bytes([padding_length] * padding_length)
 
    cifrado = encryptor.update(datos_padded) + encryptor.finalize()
    return iv, cifrado
 
def descifrar_aes(iv: bytes, cifrado: bytes, clave: bytes) -> bytes:
    """Descifra datos con AES-256-CBC."""
    cipher = Cipher(algorithms.AES(clave), modes.CBC(iv), backend=default_backend())
    decryptor = cipher.decryptor()
 
    datos_padded = decryptor.update(cifrado) + decryptor.finalize()
 
    # Remover padding
    padding_length = datos_padded[-1]
    return datos_padded[:-padding_length]
 
# Ejercicio 3.1: Cifra y descifra un mensaje
clave = os.urandom(32)  # 256 bits
mensaje = b"Datos confidenciales del paciente: Juan Perez, ID: 12345"
 
iv, cifrado = cifrar_aes(mensaje, clave)
print(f"Cifrado (hex): {cifrado.hex()[:64]}...")
 
descifrado = descifrar_aes(iv, cifrado, clave)
print(f"Descifrado: {descifrado.decode()}")
 
# Ejercicio 3.2: Intenta descifrar con clave incorrecta
clave_incorrecta = os.urandom(32)
try:
    descifrar_aes(iv, cifrado, clave_incorrecta)
except Exception as e:
    print(f"Error con clave incorrecta: {type(e).__name__}")

Experimenta:

  1. ¿Qué pasa si reutilizas el mismo IV para dos mensajes diferentes?
  2. ¿Dónde almacenarías la clave de cifrado de forma segura?
  3. ¿Por qué es importante que el IV sea único pero no necesita ser secreto?

Parte 4: Firmas digitales para no repudio (25 min)

Las firmas digitales prueban quién creó un mensaje y que no fue alterado.

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
 
# Generar par de claves RSA
clave_privada = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)
clave_publica = clave_privada.public_key()
 
def firmar(mensaje: bytes, clave_privada) -> bytes:
    """Firma un mensaje con clave privada."""
    return clave_privada.sign(
        mensaje,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()
    )
 
def verificar_firma(mensaje: bytes, firma: bytes, clave_publica) -> bool:
    """Verifica firma con clave pública."""
    try:
        clave_publica.verify(
            firma,
            mensaje,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        )
        return True
    except Exception:
        return False
 
# Ejercicio 4.1: Firma y verifica un documento
documento = b"Transfiero $10,000 a la cuenta 123456789"
firma = firmar(documento, clave_privada)
print(f"Firma válida: {verificar_firma(documento, firma, clave_publica)}")
 
# Ejercicio 4.2: Intenta verificar documento alterado
documento_alterado = b"Transfiero $100,000 a la cuenta 123456789"
print(f"Firma válida (alterado): {verificar_firma(documento_alterado, firma, clave_publica)}")

Experimenta:

  1. ¿Por qué solo la clave privada puede firmar pero cualquiera con la pública puede verificar?
  2. Si alguien altera el monto de la transacción, ¿qué pasa con la verificación?
  3. ¿Cómo se relaciona esto con el principio de no repudio?

Entregable

Desarrolla un mini sistema de documentos firmados que:

  1. Permita crear un “documento” (string con contenido)
  2. Genere un hash del documento
  3. Firme el hash con una clave privada
  4. Exporte el documento + firma a un archivo JSON
  5. Permita verificar la autenticidad de un documento importado
# Estructura sugerida del archivo JSON
{
    "contenido": "Texto del documento...",
    "hash": "sha256_del_contenido",
    "firma": "firma_digital_en_base64",
    "fecha": "2024-01-15T10:30:00Z",
    "firmante": "identificador_del_firmante"
}

Criterios de evaluación:

  • El código funciona correctamente
  • Detecta correctamente documentos alterados
  • Maneja errores apropiadamente
  • Incluye comentarios explicando los principios CIAAN aplicados

Reflexión

Después de completar el laboratorio:

  • ¿Qué principio CIAAN protege cada mecanismo criptográfico?
  • ¿Por qué no deberías inventar tus propios algoritmos de cifrado?
  • ¿Qué pasaría si la clave privada de una organización es comprometida?

Navegación:Anterior | Inicio | Siguiente: Taller de proyecto