Piattaforma di fiducia
Il funzionamento interno della piattaforma: ciò che fa durante il voto, le regole che si impone e ciò che il registro consente di controllarne in seguito.
Questa pagina descrive tali regole a livello di principi, come il libro bianco: database, finestra di firma, trasporto, pubblicazione, gestione dei segreti, hosting. Non sostituiscono la verifica: ogni affermazione della piattaforma è pubblicata nel registro e si controlla senza di essa.
Protocollo v1
Fidata durante il voto, verificabile in seguito.
La piattaforma è una terza parte fidata la cui fiducia è limitata nel tempo. Questa esposizione è una scelta progettuale deliberata e documentata, non una svista.
-
Durante il voto
Ciò che le viene affidato
Serve la pagina di voto, consegna le chiavi segrete nella modalità di provisioning predefinita e riceve ogni scheda firmata sulla sessione VoteLink dell’elettore. Durante questa finestra sa transitoriamente chi vota e, nella modalità predefinita, quale chiave ha consegnato a chi.
-
In seguito
Ciò che si verifica senza di essa
Ogni sua affermazione è materializzata nel registro pubblico e verificabile in modo indipendente. Le due facce del registro, presenze e schede, sono pubblicate in modo che non si possano unire in un legame elettore-scheda.
Il livello di fiducia si imposta per elezione: in modalità BYO-only, in cui ogni elettore porta la propria chiave, la piattaforma non detiene mai il segreto di firma di alcun elettore e la finestra di fiducia si riduce alla sola ricezione delle schede.
Ciò a cui impegna, e non impegna, il ruolo di «terzo di fiducia» è scritto nella carta. Non è né un accreditamento, né una certificazione rilasciata da un’autorità, né un marchio.
La carta del terzo di fiduciaPostgreSQL, arbitro unico.
Ogni invariante esposto agli utenti è imposto in PostgreSQL da scritture condizionali protette e vincoli di unicità, mai da uno stato in memoria di un processo: corretto per costruzione, qualunque sia il numero di worker e di istanze, senza ordine dei lock né stalli.
Le regole iscritte nello schema
-
ballots (election_id, key_image)unicità - Un’immagine di chiave vota una sola volta per elezione. Una rete di sicurezza che regge anche di fronte a un bug applicativo.
-
ring_keys (election_id, public_key)unicità - Una chiave pubblica compare una sola volta tra i membri degli anelli dell’elezione.
-
chain_blocks (election_id, block_number)unicità - La protezione assoluta contro le biforcazioni: uno scrittore concorrente perdente fallisce e riprova sulla nuova testa della catena.
-
ballotssolo aggiunta · trigger - Ogni UPDATE o DELETE solleva un’eccezione. Unica eccezione codificata: il flag is_chain_published, portato da false a true nella transazione che convalida un blocco.
-
chain_blockssolo aggiunta · trigger - La stessa regola per le ancore della catena; unica eccezione: lo stato OpenTimestamps, a senso unico pending → completed.
-
ballots.payloadbytea - I byte firmati, memorizzati così come sono. Mai in un tipo JSON normalizzante: jsonb riordina le chiavi e riscrive gli spazi, il che romperebbe la verifica esatta al byte.
-
ballots.idUUID v4, senza marca temporale - Un identificativo casuale e nessuna data di creazione: nulla rivela l’ordine di deposito.
Scritture senza concorrenza possibile
- Scritture protette. Il passaggio di has_voted, il tetto di distribuzione delle chiavi e la rivendicazione di una chiave sono UPDATE condizionali: zero righe modificate equivale a un rifiuto. Mai una lettura-modifica-scrittura in memoria.
- La crittografia fuori dai lock. La verifica della firma, puro calcolo su dati pubblici, viene eseguita prima della transazione di scrittura: la crittografia non tiene mai un lock.
- Un’elezione aperta, riaffermata. Al deposito, lo stato aperto dell’elezione è riaffermato nella transazione, serializzata rispetto alla chiusura: una scheda è convalidata prima della chiusura e pubblicata da questa, oppure rifiutata. Mai una scheda memorizzata che la catena escluderebbe.
- Blocchi serializzati. I blocchi sono prodotti da attività in coda, serializzate per elezione; la riga convalidata nel database è l’arbitro di ogni blocco.
Conservare solo il necessario, non datare nulla.
La piattaforma non memorizza nulla di cui il protocollo non abbia bisogno e non pubblica nulla che dati o identifichi una scheda. La marcatura temporale dei voti è trattata come un canale laterale, eliminato da un capo all’altro.
Minimizzazione
- I dati dell’elettore. Il suo indirizzo e-mail e, facoltativamente, il nome e il peso: all’organizzatore non si chiede altro.
- Segreti cifrati, poi cancellati. Le chiavi segrete di voto sono cifrate a riposo ed eliminate nel momento in cui vengono usate. Una volta consegnata, la chiave non esiste più nel database: sopravvive, cifrata, solo in una cache di al massimo 180 minuti per una nuova consegna, e ne viene cancellata al voto.
- Memoria azzerata. I segreti transitori sono azzerati esplicitamente, lato PHP (oggetti-valore basati su sodium_memzero) come lato Rust/WASM (buffer azzerati).
- Nessun tracciamento. Né analytics né tracciamento, sulla pagina di voto come sul resto del sito: restano solo i log del server.
Igiene della cronologia
- Nessuna marca temporale sulle schede. Né nel database né nel registro; identificativi UUID v4 casuali su tutta la superficie pubblica.
- Pubblicazione per lotti. Le schede escono in lotti di almeno 600, secondo un calendario casuale, ordinate per immagine di chiave; il registro delle presenze è pubblicato una sola volta, alla chiusura.
- Pulizia fisica. PostgreSQL contrassegna ogni riga con la transazione che l’ha scritta: una scheda e il passaggio della relativa presenza condividono per un momento lo stesso contrassegno, assente da un’esportazione logica ma leggibile con un accesso diretto al database. Un’attività eseguita due volte al giorno riscrive queste righe sotto un’unica transazione muta, poi esegue un VACUUM: un contrassegno recente sopravvive al massimo un ciclo di pulizia.
Proteggere il momento in cui la chiave è in memoria.
La chiave segreta dell’elettore vive nel suo browser solo per la durata della pagina di voto. È il momento più esposto lato client, e quello che la piattaforma protegge con maggior rigore.
La pagina di voto
- Autonoma. Una pagina senza framework, fuori dall’applicazione dell’organizzatore. Ogni navigazione fuori dal voto è un ricaricamento completo, che cancella la chiave dalla memoria.
- La CSP più rigorosa. Solo prima parte, nessuno script di terzi, nessuna analytics; esecuzione WebAssembly consentita, invii di moduli disattivati a favore di un invio esclusivamente via fetch.
- L’integrità del codice che firma. Gli asset compilati portano impronte di integrità delle sotto-risorse (SHA-384): un nodo CDN compromesso non può alterare silenziosamente il percorso del codice di firma.
- Un sottodominio dedicato. Il voto risiede su voting.condorcet.vote, con cookie limitati all’host: il suo stato di sessione è isolato dal resto del sito.
Trasporto, link e sessioni
- TLS fino all'applicazione. La cifratura TLS è gestita dal server web dell'applicazione stessa, Caddy (scritto in Go, tramite FrankenPHP), senza proxy intermedi. I suoi certificati Let's Encrypt sono emessi e rinnovati automaticamente, ogni accesso HTTP è reindirizzato verso HTTPS e si applicano le sue impostazioni TLS moderne predefinite: TLS 1.3 privilegiato, 1.2 come minimo.
- Nessun log di accesso sul voto. Il sottodominio di voto non viene mai registrato nei log: i suoi indirizzi contengono il token del VoteLink e dei log con data e ora ricreerebbero la cronologia dei voti che il database si rifiuta di conservare.
- Direttamente verso l’origine, su TLS. Anelli, distribuzione delle chiavi e deposito delle schede viaggiano direttamente tra il browser e la piattaforma. Nessuna CDN si interpone per i dati di voto; solo gli asset statici compilati sono messi in cache ai margini della rete.
- Un link di capacità, senza account. L’elettore non crea né account né password: il suo VoteLink, inviato per e-mail dalla piattaforma, è una capacità al portatore. Viene memorizzata solo l’impronta del token; il link è legato a un solo elettore, la sua sessione ha un perimetro ristretto ed è soggetto a una limitazione della frequenza.
- Sessioni lato server. Le sessioni sono conservate in Valkey (Redis). Nel browser, solo lo stato strettamente necessario: sessione, lingua, tema.
- Il resto del sito. Tutto, script e WebAssembly compresi, è servito in prima parte, sotto una CSP rigorosa; nessuna origine di terzi sulle pagine pubbliche.
- Gli organizzatori. Accesso con password o passkey, secondo fattore TOTP facoltativo, tentativi limitati per identificativo e per indirizzo IP.
Ciò che l’applicazione non può riscrivere.
Un blocco è valido se e solo se i suoi byte producono l’impronta convalidata e la sua firma si verifica, ovunque venga letto. L’archiviazione aggiunge le proprie barriere.
Isolamento della pubblicazione
- Un’archiviazione separata. I file della catena risiedono nel proprio bucket di archiviazione a oggetti, con le proprie credenziali di accesso, separati da qualsiasi altro contenuto archiviato e serviti dal proprio nome host CDN: un difetto in un percorso di caricamento non può mai scrivere nella catena.
- Una scrittura unica. Il bucket attiva il blocco degli oggetti del fornitore: una volta scritto, un file di blocco non può essere né sovrascritto né eliminato, nemmeno con le credenziali di archiviazione della piattaforma. Completa i trigger del database e la catena di impronte.
- Byte grezzi. I blocchi sono serviti così come sono; nessuno strato del framework può riformattarli. Poiché il contenuto è deterministico, una scrittura ripetuta è idempotente.
La chiave di firma
- Uno strumento fissato. Ogni blocco è firmato in OpenPGP v6 (RFC 9580, Ed25519) da una versione fissata e inclusa di Sequoia sq, in attività in background; nessun calcolo di firma lato PHP.
- Chiavi private fuori dal database. I certificati pubblici sono nel database; le chiavi private non vi entrano mai. Sono conservate nel gestore di segreti di OVHcloud (OKMS), secondo i più elevati standard di sicurezza: cifrate a riposo, un dominio isolato per ambiente, accesso tramite certificato client in TLS reciproco. OKMS si limita a custodirle: la firma resta locale, legge una versione fissata della chiave e ne controlla l'impronta.
- Una rotazione che contiene. Alla rotazione, la chiave uscente riceve una scadenza in quello stesso istante e le sue versioni sono disattivate: una chiave ritirata continua a verificare, ma non firma più.
- Ciò che la firma non dimostra. Dimostra che la piattaforma ha prodotto un blocco, non che non ne abbia riscritto la storia, poiché detiene la chiave. L’immutabilità deriva dal mirroring indipendente, e l’ancoraggio OpenTimestamps di ogni blocco dimostra quando i suoi byte esistevano.
Dove gira, come è costruita.
La gestione operativa in senso lato non è descritta qui; figurano solo i punti che sostengono una garanzia.
Hosting
- In Francia. La piattaforma è ospitata in Francia e tutto è servito dal suo dominio: nessun servizio di terzi si carica nel browser degli elettori.
- Uno stack essenziale. PostgreSQL per i dati; Valkey per sessioni, code e cache, mai come archivio principale. Code di attività isolate, perché un picco su una non privi mai le altre dei worker.
- Segreti fuori dalla configurazione. Negli ambienti remoti nessuna credenziale risiede nei file di ambiente: sono tutte custodite da OKMS, il gestore di segreti di OVHcloud, con un dominio isolato per ambiente.
Disciplina di ingegneria
- La vera crittografia nei test. La suite di test esercita il vero modulo WebAssembly, mai una simulazione, lato server come nel browser, fino a percorsi di voto completi guidati dal browser.
- Vettori fissati. Il nucleo crittografico fissa vettori di protocollo: qualsiasi modifica silenziosa di una stringa di dominio, di un formato o di una disposizione di byte fa fallire la build. Esegue inoltre analisi di malleabilità bit per bit e obiettivi di fuzzing su tutti i suoi parser, e verifica le proprie dipendenze in CI.
- Specifiche sincronizzate. Le specifiche sono versionate con il codice e mantenute allineate a esso per convenzione esplicita; il libro bianco e queste pagine ne sono la forma pubblicata.
Ciò che resta una questione di fiducia.
Questi limiti sono documentati, non nascosti. Riguardano soprattutto la finestra del voto; in seguito, il registro delimita ciò che una piattaforma potrebbe fare senza essere vista.
Ciò che occorre affidarle
- Una piattaforma malevola al momento del voto. In modalità chiave generata dal server, potrebbe precalcolare l’immagine di chiave di ogni chiave consegnata e deanonimizzare le schede. Le chiavi importate o registrate tolgono questo potere; le elezioni BYO-only eliminano ogni segreto detenuto dal server.
- Una partecipazione fabbricata. Potrebbe segnare un assente come votante e aggiungere una scheda entro i limiti pubblicati; solo l’elettore interessato può rilevarlo, verificando la propria riga nel registro delle presenze.
- Il browser durante la firma. Un’iniezione di script durante la finestra di firma resta il rischio residuo lato client: la CSP lo riduce al minimo senza poterlo eliminare.
- I recapiti a riposo. Nomi e indirizzi e-mail degli elettori sono conservati in chiaro, perché i VoteLink partono per e-mail e l’organizzatore ha bisogno di un elenco leggibile: una compromissione del database li esporrebbe. Le chiavi segrete di voto, invece, sono sempre cifrate.
- L’archiviazione fisica. I WAL archiviati, i backup e i log di accesso web restano una questione di infrastruttura e di conservazione.
- Una revisione esterna, in arrivo. È prevista una revisione indipendente del protocollo e della sua implementazione; il relativo rapporto sarà collegato dalla pagina sicurezza.
Ciò che delimita questa fiducia
- Il registro. Firme ad anello valide, nessuna chiave che abbia firmato due volte, non più schede che elettori registrati: tutto si controlla a partire dal solo registro pubblicato.
- Il riconteggio. Il risultato si ricalcola a partire dal registro, con un software che non è quello della piattaforma.
- La catena e i suoi mirror. File grezzi, firmati e concatenati, che chiunque può conservare: una riscrittura diventa evidente per qualsiasi testimone che abbia conservato una testa di catena precedente.
- Il codice che conta. Il nucleo crittografico (CryptoVote) e la libreria di scrutinio (CondorcetPHP) sono open source: ciò che firma, verifica e conta è ispezionabile.
- Impegni scritti. La carta stabilisce ciò che la piattaforma si impegna a fare, e a non fare: un registro pubblicato non viene mai ritirato né modificato su richiesta dell’organizzatore.
Vedi anche
- Registro pubblico Ciò che ogni elezione pubblica, indipendentemente dal mezzo di trasmissione: definizione, anelli, registro delle presenze, schede.
- Chiavi della piattaforma I certificati OpenPGP v6 che firmano i blocchi, la loro rotazione e il loro punto di accesso per le macchine.
- Procedura di verifica Verificare un'elezione da cima a fondo: dal solo registro, oppure con la blockchain.