--- name: secret_store kind: function lang: cpp domain: infra version: "1.0.0" purity: impure signature: "fn_secret::encrypt(plaintext) -> vector; fn_secret::decrypt(blob) -> string; fn_secret::is_strong() -> bool" description: "Encrypt/decrypt sensitive strings for local SQLite storage. Windows: DPAPI (user-bound, machine-local, cryptographically strong). Linux/WSL fallback: XOR with per-user seed key (not crypto-secure, shows warning). Used by agents_dashboard to store API keys." tags: [security, credentials, dpapi, encrypt, infra, agents] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [infra/secret_store.h] tested: false tests: [] test_file_path: "" file_path: "cpp/functions/infra/secret_store.cpp" framework: "" params: - name: plaintext desc: "Sensitive string to encrypt (API key, password, token)." - name: blob desc: "Opaque byte vector returned by encrypt(), stored as SQLite BLOB column." output: "encrypt returns vector blob (empty on failure). decrypt returns plaintext string (empty on failure). is_strong() returns true on Windows (DPAPI), false on Linux (XOR fallback)." --- # secret_store Encrypt/decrypt sensitive credentials for local SQLite storage. ## Ejemplo ```cpp #include "infra/secret_store.h" // Store API key encrypted: std::vector blob = fn_secret::encrypt("my-api-key-here"); // Insert blob into SQLite BLOB column via sqlite3_bind_blob()... // Recover: std::string key = fn_secret::decrypt(blob); // Base64 helpers for TEXT columns: std::string b64 = fn_secret::encrypt_b64("my-api-key-here"); std::string back = fn_secret::decrypt_b64(b64); // Platform check (show warning on Linux): if (!fn_secret::is_strong()) { fn_log::warn("[security] apikey stored with weak Linux fallback encryption"); } ``` ## Cuando usarla Antes de guardar una API key, token o contrasena en SQLite local. Siempre usar `fn::local_path("app.db")` para la DB. En Windows (DPAPI) la clave nunca sale de la maquina. En Linux, mostrar aviso en UI de que la proteccion es basica. ## Gotchas - **DPAPI is Windows-only**: el blob cifrado en Windows NO se puede descifrar en Linux y viceversa. Si el usuario mueve la DB entre plataformas, las credenciales se pierden — debe reingresar la apikey. - **Linux fallback NO es criptograficamente seguro**: XOR con semilla derivada de username+hostname. Previene lectura casual pero no protege contra atacante con acceso al sistema. - **CryptProtectData es sincrono**: no llamar desde el thread principal con datos grandes. Para una apikey (tipicamente <200 bytes) el coste es despreciable. - Linkear `crypt32.lib` en Windows: el `.cpp` tiene `#pragma comment(lib, "crypt32.lib")` — no necesita entry en CMakeLists para MSVC. Con MinGW se enlaza automaticamente si se incluye `wincrypt.h`.