Architettura di sicurezza
1. Scopo del documento
Questo documento descrive il modello di sicurezza adottato da Dopodi per proteggere il vault degli utenti. È scritto per essere verificabile: ogni affermazione tecnica si riferisce a primitive crittografiche standard e a scelte architetturali che chiunque con competenze in sicurezza informatica può valutare.
Il documento non sostituisce un audit di sicurezza formale, non è previsto e non dà — garanzie legali. È uno strumento di trasparenza.
2. Modello a tre strati
La sicurezza di Dopodi si articola in tre strati indipendenti. L'indipendenza è il principio critico: il compromesso di un singolo strato non implica l'accesso ai dati dell'utente.
Cifratura — cosa sai
Master password → PBKDF2-SHA256 (≥ 600 000 iterazioni) → chiave AES-GCM-256
La master password non esce mai dal browser. Con accesso al database, il vault rimane indecifrabile.
Secondo fattore — cosa possiedi
TOTP MFA tramite app authenticator (RFC 6238 / TOTP). Attivo come strato opzionale ma raccomandato.
Blocca gli attacchi che compromettono solo l'email dell'utente.
Autenticazione — chi sei
OTP via email (8 cifre, monouso) → Supabase Auth → JWT firmato → RLS su Postgres
Identifica l'utente e controlla quali record cifrati può scaricare dal server.
3. Strato 3 — Cifratura del vault
Il vault è cifrato interamente lato client, prima di raggiungere il server. Il server non riceve mai né la master password né la chiave di cifratura derivata.
3.1 Derivazione della chiave
All'attivazione del vault, l'utente sceglie una master password. Da essa viene derivata la chiave di cifratura tramite PBKDF2-SHA256 con:
3.2 Cifratura dei dati
Ogni operazione di cifratura usa AES-GCM-256 con un IV (Initialization Vector) fresco e casuale generato per ciascuna operazione. Non viene mai riutilizzato lo stesso IV con la stessa chiave.
3.3 Verifica della master password (canary)
Per evitare tentativi di decifratura con password errata, al setup viene cifrato un valore noto (canary) con la chiave derivata. Ad ogni apertura del vault, il canary viene decifrato: se il risultato non corrisponde al valore atteso, la password è errata e la decifratura non procede. Il canary è cifrato — non rivela informazioni sulla master password.
4. Strato 2 — MFA TOTP
Il secondo fattore è basato su TOTP (Time-Based One-Time Password) secondo RFC 6238. L'utente registra un'app authenticator (Google Authenticator, Authy, ecc.) che genera un codice a 6 cifre ogni 30 secondi.
Il MFA TOTP protegge dallo scenario in cui l'attaccante ha compromesso la casella email dell'utente e tenta di autenticarsi con un OTP intercettato. Senza il dispositivo fisico con l'app authenticator, l'autenticazione fallisce.
Nota: il MFA TOTP agisce sullo strato di autenticazione. Anche bypassando entrambi gli strati 1 e 2, l'attaccante non ottiene la chiave di cifratura del vault — che dipende esclusivamente dallo strato 3 (master password).
5. Strato 1 — OTP email
L'autenticazione primaria usa un OTP a 8 cifre inviato all'email dell'utente, monouso e con scadenza breve. Gestita tramite Supabase Auth, che emette un JWT firmato. Il JWT viene usato per applicare le Row Level Security policies su Postgres, limitando l'accesso ai soli record dell'utente autenticato.
6. Separazione tra autenticazione e cifratura
Il principio architetturale fondamentale di Dopodi è la separazione netta tra i piani di autenticazione e di cifratura:
Autenticazione (server)
Email + OTP → identifica chi sei
TOTP MFA → verifica cosa possiedi
JWT + RLS → controlla quali record cifrati puoi scaricare
Cifratura (browser)
Master password → cosa puoi leggere
PBKDF2-SHA256 → deriva la chiave AES
AES-GCM-256 → decifra il vault localmente
I due piani sono indipendenti. L'autenticazione controlla quali ciphertext l'utente può scaricare. La master password controlla se può leggerli. Un attaccante che bypassa l'autenticazione (inclusi strati 1 e 2) ottiene solo ciphertext inutilizzabile senza la master password.
7. Zero-knowledge — cosa vede il server
La tabella elenca esplicitamente cosa Dopodi (il server) può e non può vedere:
| Dato | Server lo vede? | Note |
|---|---|---|
| Email dell'utente | Sì | Necessaria per autenticazione OTP |
| Piano attivo, metadati account | Sì | Necessari per erogare il servizio |
| Salt di derivazione | Sì | Non segreto — protegge solo da rainbow table |
| Ciphertext del vault | Sì | Inutilizzabile senza la chiave derivata |
| Master password | No | Mai trasmessa, mai salvata |
| Chiave di cifratura AES derivata | No | Esiste solo in memoria del browser durante la sessione |
| Contenuto del vault (credenziali, ricordi, istruzioni) | No | Cifrato lato client prima della trasmissione |
8. Key escrow per i fiduciari
Il sistema di consegna ai fiduciari è progettato attorno a RSA-OAEP 2048-bit SHA-256. Quando l'utente nomina un fiduciario, una copia della chiave di cifratura del vault viene cifrata con la chiave pubblica del fiduciario. Solo il fiduciario — con la propria chiave privata — può aprire quella copia.
Nota implementativa: il sistema key escrow è progettato e documentato. Al momento della pubblicazione di questo documento, l'implementazione è in roadmap (priorità P3). I fiduciari sono configurabili nell'app, ma il meccanismo di consegna cifrata è in sviluppo.
9. Threat model
| Scenario di attacco | Esito | Perché |
|---|---|---|
| Esfiltrazione del database | Protetto | Il server contiene solo ciphertext. Inutilizzabile senza la master password. |
| Compromissione email | Protetto (con MFA attivo) | MFA TOTP blocca l'accesso anche con email compromessa. Senza MFA, l'autenticazione è bypassabile — il vault rimane però cifrato. |
| Email + MFA compromessi | Protetto | L'accesso alla dashboard non include la chiave di cifratura. Il vault è accessibile solo con la master password. |
| Obbligo legale (ordine del tribunale) | Protetto | Dopodi può consegnare solo ciphertext. Il ciphertext senza la chiave derivata è inutilizzabile. |
| Compromissione della master password (senza accesso al device) | Parzialmente protetto | La master password da sola non basta: serve anche l'autenticazione (OTP + eventuale MFA) per scaricare il ciphertext. |
| Compromissione completa del dispositivo dell'utente | Non protetto | Se l'attaccante controlla il dispositivo durante una sessione attiva, può accedere alla chiave in memoria. È la superficie d'attacco irriducibile di qualsiasi sistema client-side. |
10. Stato di implementazione
| Componente | Stato |
|---|---|
| OTP email (strato 1) | Implementato |
| MFA TOTP (strato 2) | Implementato |
| Master password → PBKDF2-SHA256 → AES-GCM (strato 3) | Implementato |
| Verifica canary | Implementato |
| Recovery codes (Emergency Kit stampabile) | Implementato |
| Key escrow RSA-OAEP per fiduciari | In roadmap (P3) |
| Passkey / WebAuthn | In roadmap (P4) |
11. Cosa questo documento non copre
— Specifiche complete delle policy RLS (Row Level Security) su Postgres
— Design delle schermate UX per master password e MFA
— Architettura di rete e configurazione Cloudflare
— Audit di sicurezza formale (previsto prima del lancio pubblico)
— Confronto dettagliato PBKDF2 vs Argon2id (Argon2id non è nativo nella Web Crypto API)
Per domande su questo documento: [email protected]