MiLegado

Cómo protegemos tus datos cuando el costo de equivocarse es tu familia.

MiLegado guarda lo que tu familia necesita si vos no estás. Por eso el modelo de seguridad es zero-knowledge: el servidor nunca ve tus datos en claro. Acá explicamos exactamente cómo, sin marketing.

Contenido

  1. TL;DR
  2. Cifrado E2E (lo que el servidor NO ve)
  3. Cómo se derivan las claves
  4. Acceso de custodios (sobres RSA)
  5. Login y 2FA
  6. Infraestructura y headers de seguridad
  7. Modelo de amenazas (qué SÍ y qué NO te protege)
  8. Reportar una vulnerabilidad

1. TL;DR


2. Cifrado E2E — lo que el servidor NO ve

Cada item (clave bancaria, mensaje, documento) se cifra antes de salir de tu dispositivo. El servidor recibe solamente el blob cifrado + un IV. Lo que hay en nuestra base de datos para tu cuenta:

Campo¿Qué guarda el server?¿Cifrado?
EmailTu email tal cualNo (lo necesitamos para login)
PasswordHash Argon2id con salHash one-way (no se puede revertir)
Título del itemBytes cifrados con AES-GCM
Contenido del itemBytes cifrados con AES-GCM
Archivos adjuntosBytes cifrados (R2 / Postgres bytea)
Vault keyNunca tocada por el serverDerivada en tu browser desde tu password
Sobre RSA del custodioVault key cifrada con su pub key
Implicancia: si nos hackean la base de datos, los atacantes ven blobs binarios. No pueden descifrarlos sin tu password — y tu password no está en la base de datos.

3. Cómo se derivan las claves

Vault key (la que cifra todos tus items)

Cuando te registrás, tu navegador genera un sal aleatorio de 16 bytes. Cada vez que ingresás tu password, derivamos la vault key haciendo:

vault_key = scrypt(password, salt, N=2^17, r=8, p=1, length=32)

Eso son ~256 MB de RAM y ~150ms en hardware típico. Diseñado para que un atacante con el blob cifrado tenga que hacer ese mismo cómputo por cada password que prueba — un ataque offline contra un password fuerte tarda años.

Cifrado del item

Cada item se cifra con AES-256-GCM usando la vault key y un IV de 96 bits aleatorio por item. GCM provee confidentialidad e integridad: si alguien modifica un byte del blob, la verificación de tag falla y el descifrado tira error en lugar de devolver basura.

Private key personal (para recibir sobres)

Generamos un keypair RSA-OAEP 2048 al signup. La private key se cifra inmediatamente con AES-GCM derivado de tu password (mismo flujo que el vault key, sal distinto) y se sube ya cifrada. La public key va plana — la usan otros users para mandarte sobres.


4. Acceso de custodios (sobres RSA-OAEP)

Cuando designás un custodio, se le manda un email con link de invitación. El custodio crea su cuenta y se genera su keypair RSA. Cuando volvés a entrar, tu navegador hace algo que el server no podría hacer:

  1. Toma tu vault key (derivada de tu password).
  2. La cifra con la public key del custodio (RSA-OAEP).
  3. Sube el resultado como "envelope" — el server lo guarda asociado a esa relación.

Si se gatilla el dead-man-switch (no hacés check-in por X días), el custodio puede pedir el envelope. Como solo su private key puede descifrarlo, recupera la vault key y a partir de ahí descifra tus items. El server no puede ayudar — no tiene ni tu vault key ni la private key del custodio.

Por qué importa: si MiLegado fuera comprometida, los atacantes verían los envelopes RSA, pero romper RSA-2048 sin la private key correspondiente está fuera del alcance de cualquier adversario actual (ataques cuánticos teóricos cambiarán esto en 10-20 años; cuando llegue ese día, migraremos a post-quantum y rotamos las claves).

5. Login y 2FA

6. Infraestructura y headers de seguridad


7. Modelo de amenazas — qué SÍ y qué NO te protege

SÍ te protege contra:
NO te protege contra:

8. Reportar una vulnerabilidad

Si encontrás algo, mandanos un mail a security@milegadoapp.com antes de publicarlo. Damos crédito en este mismo documento si querés. Sin programa de bounty oficial todavía, pero si el bug es serio te mandamos algo material — escribinos.

También respetamos la RFC 9116 security.txt.

Última actualización del documento: ahora
Si algo de esto cambia, lo actualizamos acá Y mandamos email a usuarios paid.