Wallet SSI — Modelo C híbrido
This content is not available in your language yet.
El wallet de identidad de Digital Jungle no es custodial puro. Es SSI real — las claves de firma viven en el Secure Enclave del usuario, no en bjungle. Esta es la decisión arquitectónica que separa el wallet de los reuso-de-KYC de Stripe Identity, Persona o Trulioo.
Los tres modelos que evaluamos
Sección titulada «Los tres modelos que evaluamos»| Modelo | Custodia de claves | Backup | Recuperación | Postura legal |
|---|---|---|---|---|
| A. Custodial puro | bjungle (KMS) | bjungle | Login + factor | bjungle es controlador |
| B. No-custodial estricto | dispositivo del usuario | ninguno | pérdida = irreversible | usuario es controlador |
| C. Híbrido (el elegido) | dispositivo del usuario | E2EE en bjungle | password + multi-device | usuario es controlador |
Modelo A es lo que hacen los reuso-de-KYC custodiales. Es lo más simple y permite “olvidé mi contraseña, mandame email” — pero deja al proveedor como controlador de los datos a ojos del regulador (GDPR Art. 4(7), Ley 1581 art. 3.d).
Modelo B es lo que prometen los “true SSI” libertarios — y lo que provoca que el 80 % de los usuarios pierda el wallet en menos de 12 meses. Sin recuperación, las claves perdidas son claves perdidas para siempre.
Modelo C mantiene SSI real para casos felices (la clave nunca sale del dispositivo) y permite recuperación auditable para casos de pérdida (re- consent vía un tenant que ya conoce al usuario; ver §Recovery abajo).
Cómo funciona en práctica
Sección titulada «Cómo funciona en práctica»┌──────────────────────────────────────────────────────────────┐│ Dispositivo del usuario (iPhone, Android, PC con WebAuthn) ││ ││ ┌─────────────────────────────────┐ ││ │ Secure Enclave / StrongBox │ ││ │ ─────────────── │ ││ │ • Par ed25519 / P-256 │ ← clave PRIVADA ││ │ • Bound a biometría / PIN │ nunca sale ││ │ • App Attest / Play Integrity │ del enclave ││ └─────────────────────────────────┘ ││ ▲ ││ │ firma assertions WebAuthn ││ │ ││ ┌─────────────────────────────────┐ ││ │ bjungle wallet app / PWA │ ││ │ • muestra credenciales │ ││ │ • orquesta consent │ ││ │ • descarga backup E2EE │ ││ └─────────────────────────────────┘ │└──────────────────────────────────────────────────────────────┘ ▲ │ HTTPS · solo Bearer JWT + assertions │┌──────────────────────────────────────────────────────────────┐│ bmonkey-api (bjungle) ││ • wallet_passkeys.public_key ← solo pubkey almacenada ││ • verifiable_credentials.jwt_vc ← firmadas con KMS bjungle ││ • wallet_backups (futuro) ← blob AES-GCM cifrado E2EE ││ clave Argon2id derivada del ││ password del usuario │└──────────────────────────────────────────────────────────────┘bjungle nunca tiene la clave privada. bjungle nunca tiene la contraseña que cifra el backup. bjungle emite las VCs (con su propia KMS key) y rutéa las presentations, pero no puede aprobarlas en nombre del usuario.
Recovery — la decisión más sensible
Sección titulada «Recovery — la decisión más sensible»Toda la seguridad de SSI se desploma si el recovery es débil. Después de evaluar cuatro caminos (email, palabras semilla, re-consent, re-KYC), adoptamos re-consent gated por bjungle:
- El usuario perdió todas las passkeys del wallet.
- Pide a un comercio donde ya verificó su identidad (ej. Cashpaya) que le
abra una solicitud nueva con
/v1/wallet/request-presentation. - El usuario aprueba con su documento real (no con passkey vieja). El
approve detecta que el wallet tiene 0 passkeys activas y emite un
wallet_session_tokenpor 1 hora — el único path donde lo emitimos automáticamente (HIGH-2 del audit T15). - El usuario enrola una passkey nueva en el dispositivo nuevo. Al completarse, todas las passkeys anteriores quedan invalidadas.
Por qué este path no es un agujero: el atacante necesitaría comprometer el canal de notificación del usuario (SMS sniffing, email phishing) Y un comercio donde la víctima ya tiene cuenta verificada lo suficientemente predispuesto a abrir un consent en su nombre. Es asimétricamente más costoso que un email-based “olvidé mi password”.
Implicaciones de privacidad
Sección titulada «Implicaciones de privacidad»| Pregunta | Respuesta |
|---|---|
| ¿bjungle puede leer mis VCs? | Sí — las VCs se almacenan cleartext en verifiable_credentials.claims jsonb. El backup E2EE futuro impedirá esto. |
| ¿bjungle puede firmar presentations sin mi consentimiento? | No — el JWT-VP se firma con la clave del Secure Enclave del usuario (Modelo C activado) o requiere el approve UI (Modelo A degraded para usuarios sin app móvil aún). |
| ¿Si bjungle desaparece, pierdo mi identidad? | Hoy sí (no hay portabilidad cross-vendor). En el futuro, el JWT-VC firmado por bjungle podrá ser verificado por cualquiera con la pubkey del JWKS — eso preserva el VALOR de la verificación incluso post-bjungle. |
| ¿Cumple con Ley 1581 colombiana? | Sí — el usuario es controlador de los datos (Art. 3.d), bjungle es encargado del tratamiento (Art. 3.e). El reuso requiere consentimiento expreso (Art. 9). |
Estado de la implementación
Sección titulada «Estado de la implementación»| Componente | Estado |
|---|---|
Tabla wallet_passkeys + funciones SECURITY DEFINER | ✅ migración 0010 |
| Endpoints WebAuthn register/login | ✅ T15 |
| Sign-count regression + revocación masiva (clon detectado) | ✅ T15 [HIGH-3] |
Backup E2EE (wallet_backups) | ⏳ móvil T20-T22 |
| Cross-device QR enroll | ⏳ móvil T20-T22 |
| Step-up para revocar passkeys (BMK-19-15) | ⏳ pre-launch obligatorio |
Referencias
Sección titulada «Referencias»- Migración:
bmonkey/backend/db-bmonkey/migrations/0010_wallet_passkeys.up.sql - Issuer:
bmonkey/backend/go-bmonkey-api/internal/service/vc_issuer.go - WebAuthn service:
bmonkey/backend/go-bmonkey-api/internal/service/webauthn_service.go - Plan de implementación móvil:
BACKLOG.mdsección “Wallet móvil (React Native)”