5.1 KiB
5.1 KiB
Design Proposal: Zero-Knowledge Secrets Manager
1. Architectural Overview
Philosophy: "Thick Client, Blind Server." The system relies on a Zero-Knowledge Architecture. The server (Node.js/PostgREST) and the database never see unencrypted secrets; they act solely as a synchronization engine for encrypted blobs. All encryption/decryption occurs on the client device (Tauri/Flutter) using keys that never leave the device.
High-Level Data Flow
- Client: Derives Master Key from (Password + Salt). Encrypts data locally.
- Transport: Sends encrypted blob (text/bytea) over HTTPS.
- Gateway: Nginx/Traefik handles SSL termination and routing.
- Auth: Node.js verifies identity (SRP-6a) and issues JWT.
- Persistence: PostgREST accepts JWT, enforces Row-Level Security (RLS), and writes blob to PostgreSQL.
2. Component Design
A. Database Layer (PostgreSQL v18+)
- Role: Storage and Authorization Engine.
- Logic: Heavily utilizes Row-Level Security (RLS) policies.
- Schema Strategy:
users: Storesverifier(SRP-6a) or hashed credentials (Argon2id).secrets: Storesencrypted_data(bytea),iv,auth_tag,owner_id,type(manual/rotated).access_policies: Join table mapping users/groups to secrets.
- Security: RLS policies ensure
SELECT * FROM secretsonly returns rows whereauth.uid() IN (access_policies).
B. Backend API (Node.js v24 + PostgREST)
- Node.js Service:
- Auth: Implements SRP-6a (Secure Remote Password) protocol.
- Business Logic: Handling billing, email alerts, secret rotation jobs, and external webhooks.
- Orchestration: Manages Redis interactions for ephemeral state.
- PostgREST:
- High-performance CRUD layer.
- Directly exposes secure views/tables.
- Consumes JWTs issued by the Node.js service for authorization.
C. Caching & State (Redis Cluster v8)
- Image Source: Official
redis:alpine(replacing deprecated Bitnami images). - Revocation Lists: Stores revoked JWT JTI claims.
- Rate Limiting: Distributed counters to block brute-force attacks.
- Pub/Sub: Real-time event bus to trigger client syncs (e.g., "Vault Updated").
D. Clients (Tauri & Flutter)
- Desktop (Tauri):
- Security: Encryption logic (AES-256-GCM / XChaCha20-Poly1305) runs in the Rust backend to prevent memory dumping attacks via browser dev tools.
- Offline: Encrypted SQLite local replica.
- Mobile (Flutter):
- Storage: Uses
flutter_secure_storagefor session tokens. - Bio-auth: Integrates FaceID/Fingerprint to unlock the local vault key.
- Storage: Uses
3. Workflows
A. Manual Secret Entry (Core Feature)
This is the standard workflow for storing static API keys, passwords, or notes.
- User Input: User enters data (e.g.,
API_KEY=12345) into the client form. - Client Encryption: The App (Tauri/Flutter) generates a random IV and encrypts the payload using the user's Master Key in memory.
- Payload Construction: Client creates a JSON payload:
{"iv": "...", "data": "encrypted_blob...", "type": "manual"}. - Sync: Client POSTs the payload to PostgREST.
- Storage: Database stores the blob. The server never sees
12345.
B. Automated Rotation (Enhancement)
- Trigger: Cron job in Node.js wakes up.
- Execution: Connects to provider (e.g., AWS), generates new keys.
- Encryption: Note: This requires a separate "Server-Side Vault" mechanism or Public Key encryption if the server needs to write secrets readable by the user.
- Update: Updates the
secretsrow with the new encrypted blob.
4. Cryptography Standards
- KDF: Argon2id (memory-hard) for deriving Master Key.
- Symmetric: AES-256-GCM or XChaCha20-Poly1305 for vault data.
- Asymmetric: RSA-4096 or ECC (Curve25519) for sharing secrets between users.
- Transport: TLS 1.3 only.
5. Infrastructure (Docker Compose Prototype)
Note: Switched to official Redis images due to Bitnami Docker Hub deprecation.
version: '3.9'
services:
# Load Balancer / SSL Termination
gateway:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
depends_on:
- api
- postgrest
# The Logic Core
api:
image: node:24-alpine
environment:
- DATABASE_URL=postgres://user:pass@db:5432/secrets_db
- REDIS_URL=redis://redis:6379
- JWT_SECRET=${JWT_SECRET}
# The Data Interface
postgrest:
image: postgrest/postgrest:latest
environment:
- PGRST_DB_URI=postgres://user:pass@db:5432/secrets_db
- PGRST_JWT_SECRET=${JWT_SECRET}
- PGRST_DB_SCHEMA=api
- PGRST_DB_ANON_ROLE=web_anon
# The Vault
db:
image: postgres:18
volumes:
- pg_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=secrets_db
- POSTGRES_PASSWORD=${DB_PASSWORD}
# The High-Speed State (Official Image)
# For a full cluster in dev, you may need a custom entrypoint or sidecar
# to bootstrap the slots. For simplicity here, we use a standalone instance
# that mimics the interface.
redis:
image: redis:alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data