Ir al contenido

Arquitectura de la Bóveda Cifrada Local

🔐 Arquitectura de la Bóveda Cifrada Local

Sección titulada «🔐 Arquitectura de la Bóveda Cifrada Local»

Criptofolio se sustenta sobre el principio de Privacidad Absoluta (Privacy-First). Las credenciales sensibles —como las claves de API de Kraken, los secretos de Binance y los tokens de agentes de IA— nunca se guardan en texto plano y jamás abandonan tu máquina local.

Al ejecutarse localmente como aplicación de escritorio o contenedor aislado, no depende de servicios de gestión de claves en la nube de terceros (como AWS KMS o Google Cloud KMS). En su lugar, implementa una bóveda criptográfica autenticada e independiente.


🛡️ Mitigaciones de Seguridad y Primitivas Criptográficas

Sección titulada «🛡️ Mitigaciones de Seguridad y Primitivas Criptográficas»

La bóveda utiliza el algoritmo AES (Advanced Encryption Standard) con clave de 256 bits en modo Galois/Counter Mode (GCM):

  • Cada secreto cifrado genera un vector de inicialización (IV) aleatorio de 12 bytes y una etiqueta de autenticación de 16 bytes.
  • Si el archivo SQLite de la base de datos (criptofolio.db) es alterado maliciosamente fuera de la aplicación, el descifrador rechaza inmediatamente el paquete corrupto.

2. Depuración de Memoria RAM en V8 (Memory Scrubbing)

Sección titulada «2. Depuración de Memoria RAM en V8 (Memory Scrubbing)»

En entornos Node.js, las cadenas de texto son primitivas inmutables gestionadas por el recolector de basura de V8. No pueden borrarse bajo demanda de la memoria RAM, quedando expuestas a volcados de memoria (heap dumps).

Para mitigar este vector de ataque:

  • El adaptador criptográfico opera exclusivamente con instancias de Buffer de Node.js.
  • Justo después de enviar las credenciales al exchange correspondiente, el backend ejecuta:
    sensitiveBuffer.fill(0);
    Esto sobreescribe de inmediato las posiciones de memoria con ceros antes de liberar el descriptor.

El backend emplea el logger Pino con rutas de ofuscación activas:

redact: ['apiKey', 'apiSecret', '*.password', 'authorization'];

Incluso en modo de depuración intensivo (debug), las credenciales se eliminan antes de escribirse en la consola o en archivos de registro.


sequenceDiagram
    autonumber
    participant User as Usuario
    participant UI as Vue UI (Ajustes de Bóveda)
    participant Hono as Backend Hono
    participant UseCase as StoreCredentialUseCase
    participant Crypto as AesGcmCryptographyAdapter
    participant DB as SQLite Bóveda (criptofolio.db)

    User->>UI: Introduce API Key y Secreto (ej. Kraken)
    UI->>Hono: POST /api/credentials/vault/KRAKEN_API
    Hono->>UseCase: storeCredential(payload)
    UseCase->>Crypto: encrypt(Buffer.from(JSON.stringify(payload)))
    Note over Crypto: Genera IV aleatorio<br/>y cifra con AES-256-GCM
    Crypto-->>UseCase: { ciphertext, iv, authTag }
    UseCase->>DB: INSERT en vault_credentials
    Hono->>Crypto: sensitiveBuffer.fill(0) (Scrub RAM)
    Hono-->>UI: 200 OK (Configurado con éxito)

Para no codificar formularios fijos en el frontend, Criptofolio utiliza un Registro Dinámico de Proveedores:

  • El backend expone la ruta GET /api/credentials/vault/providers, devolviendo el esquema y los campos requeridos por cada plataforma:
    [
    {
    "id": "KRAKEN_API",
    "name": "Kraken",
    "fields": [
    { "key": "apiKey", "label": "API Key", "type": "text" },
    { "key": "apiSecret", "label": "API Secret", "type": "password" }
    ]
    }
    ]
  • La interfaz en Vue genera los campos de entrada de forma reactiva a partir de esta definición, facilitando añadir nuevos exchanges sin tocar la vista.

El Asesor de Cartera con IA reutiliza esta bóveda para las claves API de sus proveedores de modelos (openai, anthropic, google, opencode, ollama-cloud), registradas bajo la categoría ai-model. Una bóveda bloqueada hace que el asesor omita todos los proveedores con clave y, como la clave maestra vive solo en memoria del proceso, un reinicio del backend la vuelve a bloquear. Ver Asesor de IA: Proveedores y Modelos y Auditoría y Privacidad.