Qué Hace Recuperable a un Formato de Almacenamiento
Cuatro formatos de almacenamiento, ordenados por recuperabilidad:
| Formato | ¿Recuperable? | Ejemplo | Método de Recuperación |
|---|---|---|---|
| Texto plano | Sí | password: hunter2 | Leer el archivo |
| Base64 | Sí | cGFzc3dvcmQ= | base64 --decode |
| Cifrado reversible (AES) | Sí | ENC[AES256:...] | Descifrar con la clave |
| Hash unidireccional (bcrypt) | No | $2b$12$... | No se puede revertir; se debe usar fuerza bruta |
Texto plano, base64 y cifrado reversible: todos recuperables. Un solo volcado de la base de datos de credenciales entrega al atacante todas las contraseñas en texto claro, para todos los usuarios, simultáneamente. Una sola brecha; exposición total.
El ejemplo de Mailman 2.x
Mailman 2.x (gestor de listas de correo GNU): almacenaba las contraseñas de los suscriptores en texto plano. El correo mensual de recordatorio de contraseña enviaba a todos los suscriptores su contraseña en texto claro. Dos defectos separados, ambos MOAD-0006:
1. Almacenamiento: texto plano en la base de datos de la lista. Un compromiso del servidor expone todas las contraseñas de los suscriptores.
2. Difusión: el correo mensual envía la contraseña en texto plano a través de SMTP al servidor de correo del suscriptor. El correo viaja en texto claro a través de múltiples saltos SMTP.
El equipo de Mailman diseñó ambos comportamientos. La recuperación era la característica: los suscriptores podían recuperar contraseñas olvidadas. El nombre Glass Safe proviene de esto: la caja fuerte contiene credenciales en forma visible. Cualquiera que llegue a la caja fuerte puede leer todo el contenido simultáneamente.
El Principio de lo Ya-Robado
Una credencial almacenada en forma recuperable es una credencial ya robada. El atacante aún no ha llegado. La brecha aún no ha ocurrido. Pero la arquitectura garantiza: cuando ocurre una brecha, todas las credenciales caen simultáneamente. Ninguna brecha ocurre de forma aislada; cada credencial en almacenamiento recuperable se transfiere al atacante en la misma operación.
MOAD-0006 vs MOAD-0004
MOAD-0004 (Secreto Registrado): credenciales escritas en registros accidentalmente. La escritura en el registro no era la intención; fue un efecto secundario de habilitar el registro de encabezados para depuración.
MOAD-0006 (Glass Safe): credenciales almacenadas en forma recuperable por diseño. La recuperación era la intención. La función de recordatorio de contraseña requería almacenar la contraseña. La función de mostrar contraseña requería almacenarla. El compromiso arquitectónico con la recuperación creó el defecto.
Distinción en una línea: MOAD-0004 coloca credenciales en registros por accidente; MOAD-0006 almacena credenciales en forma recuperable a propósito. Las correcciones operan en capas diferentes.
Estructural vs Accidental
La distinción arquitectónica entre MOAD-0006 y MOAD-0004 determina la estrategia de corrección. Una escritura accidental en el registro: corregir la capa de serialización. Un almacenamiento diseñado para recuperación: rediseñar la funcionalidad que requería la recuperación.
Por qué funciona bcrypt
Una función hash unidireccional acepta una contraseña y produce un resumen de longitud fija. Dado el resumen, la contraseña original no puede recuperarse. No es 'difícil de recuperar': es imposible revertir. La función se ejecuta en una sola dirección.
Tres propiedades requeridas para el almacenamiento de credenciales:
1. Unidireccional (resistencia a la preimagen). Dado hash(password), ningún algoritmo recupera password más rápido que por fuerza bruta. bcrypt, scrypt y argon2 cumplen esta propiedad.
2. Salt. Un valor aleatorio que se antepone a la contraseña antes de aplicar el hash. Misma contraseña, distinto salt, distinto hash. Propósito: derrota a las tablas arcoíris (diccionarios de hashes precalculados). Sin salt: un atacante calcula hash('password123') una sola vez y verifica simultáneamente a 1 millón de usuarios. Con salt: cada usuario tiene un hash único incluso para la misma contraseña.
3. Lento por diseño. bcrypt acepta un factor de trabajo. Mayor factor de trabajo: más iteraciones, más tiempo de cómputo por intento de hash. Inicio de sesión: 300 ms para calcular un hash. Aceptable. Fuerza bruta: 300 ms por intento. A mil millones de intentos: 9,5 años por contraseña. Inaceptable para un atacante. La lentitud es una característica, no un defecto.
import bcrypt
# Almacenar: hash unidireccional con salt
def store_password(plaintext: str) -> bytes:
return bcrypt.hashpw(plaintext.encode(), bcrypt.gensalt(rounds=12))
# Verificar: hashear el candidato y comparar los resúmenes
def verify_password(plaintext: str, stored_hash: bytes) -> bool:
return bcrypt.checkpw(plaintext.encode(), stored_hash)
# NUNCA almacenado: la contraseña en texto plano
# NUNCA recuperado: el texto plano del hash
# Restablecimiento de contraseña, no recordatorio de contraseña
El compromiso
El hash unidireccional hace imposible la recuperación de contraseñas. Un usuario que olvide su contraseña no puede recibirla de vuelta. No puede existir un correo de recordatorio de contraseña. La experiencia del usuario cambia: «¿olvidaste tu contraseña? restablécela». No es una degradación: es un límite de seguridad. El sistema que no puede recuperar una contraseña no puede filtrar una contraseña.
Una brecha de base de datos que expone hashes bcrypt: todos los hashes visibles, ninguna contraseña visible. Un atacante debe forzar cada hash individualmente, a 300 ms por intento, con sal por usuario que derrota las tablas precomputadas. Una brecha que expone contraseñas en texto plano: exposición total e inmediata.
La encriptación fuerte no es suficiente
Una auditoría de seguridad identifica un sistema de almacenamiento de credenciales. Las contraseñas se almacenan usando cifrado AES-256-CBC con una clave del lado del servidor. El informe de auditoría lo marca como un defecto de Glass Safe.
El equipo de ingeniería responde: 'AES-256 es el cifrado simétrico más fuerte disponible. La clave reside en un módulo de seguridad de hardware. Ningún atacante puede descifrar estas contraseñas.'