Pensi che implementare i nonce sia semplice? Ripensaci. Che tu stia costruendo protocolli onchain o infrastrutture offchain, una corretta implementazione dei nonce è una delle parti più difficili della sicurezza crittografica. Approfondiamo perché la protezione contro il replay è più difficile di quanto sembri 👇
2/ Prima di tutto, comprendiamo le firme digitali. Nella crittografia a chiave pubblica (come BLS), hai una chiave privata che firma i messaggi e una chiave pubblica che li verifica. In Ethereum: indirizzo = hash della chiave pubblica messaggio = hash della transazione firma = 64 byte di prova crittografica
3/ Ecco il problema: la matematica nella maggior parte dei protocolli crittografici a chiave pubblica non limita quante volte una firma può essere verificata rispetto allo stesso messaggio. Una volta che hai una firma valida, puoi riprodurla all'infinito. Questo apre la porta agli attacchi di riproduzione.
4/ Inserisci il nonce: un "numero usato una sola volta" che previene gli attacchi di replay. Quando un consumatore riceve un messaggio con un nonce, verifica se quel nonce è stato usato in precedenza. Se sì → rifiuta. Le transazioni Ethereum utilizzano questo schema.
5/ Ma l'implementazione dei nonce è ingannevolmente complessa. Requisiti chiave: - I nonce NON devono MAI essere riutilizzabili (su questa catena o su altre) - Devono prevenire attacchi di replay in modo permanente - Necessitano di meccanismi per gestire la crescita dello storage - Devono essere resistenti agli attacchi di front-running
6/ La soluzione ingenua: memorizzare tutti i nonce in un database per sempre. Questo presenta due problemi principali: a) Crescita illimitata dello spazio di archiviazione (soprattutto con attacchi di spam) b) Vulnerabilità agli attacchi di front-running Il problema (a) è più facile da risolvere rispetto al (b). Affrontiamo prima lo spazio di archiviazione...
7/ I nonce basati su timestamp risolvono la crescita dello storage! Usa timestamp + periodo di scadenza. I nonce più vecchi di 5 minuti vengono eliminati dal database. Ma che dire dei messaggi simultanei dallo stesso account? Condividono un timestamp. Soluzione: timestamp + random_bytes per un'unicità granulare.
8/ Il front-running è la parte complicata. Attori malintenzionati possono intercettare firme valide, eseguire il front-running per contrassegnare i nonce come utilizzati, e poi la chiamata dell'utente legittimo viene rifiutata. Questo è problematico onchain con operazioni in batch se una cattiva firma rifiuta un intero batch. Per offchain: usa la crittografia TLS! Non lasciare mai che un attore malintenzionato veda il nonce o la firma.
9/ Non dimenticare la persistenza! Se la tua cache dei nonce è solo in memoria, gli attaccanti possono riprodurre nonce vecchi dopo i riavvii del sistema. Persisti sempre lo stato dei nonce in uno storage durevole e ricaricalo all'avvio. Cache solo in memoria = finestra di vulnerabilità per la riproduzione.
10/ Nonce unici per consumatore! Quando si trasmette a più utenti, ciascuno dovrebbe ricevere un messaggio/firma diverso. Altrimenti, sei vulnerabile ad attacchi Man-in-the-Middle in cui un ricevente inoltra il messaggio, impersonando il mittente originale.
11/ I nonce incrementali (come Ethereum, nonce = nonce precedente + 1) hanno il loro posto, ma attenzione! Creano enormi sfide per l'infrastruttura offchain: messaggi fuori ordine, problemi di sincronizzazione e scenari di recupero complessi. Usali solo se sei sicuro che i messaggi arriveranno (o devono arrivare) in sequenza.
Riepilogo - Checklist per l'implementazione dei nonce: ✅ Utilizzare i nonce per prevenire attacchi di replay ✅ Persistente stato del nonce attraverso i riavvii ✅ Implementare meccanismi di scadenza (timestamp + pulizia) ✅ Rendere i nonce unici per ogni destinatario ✅ Proteggere contro il front-running con canali crittografati ✅ Evitare nonce incrementali a meno che l'ordine non sia garantito La sicurezza è nei dettagli! 🛡️
1,36K