Per rendere più chiare le spiegazioni, supponiamo che si tratti di una sorta di memoria distribuita in cui un messaggio sarebbe
“Who has file A? Please send it to me.”
e il nodo con file lo invierà al mittente. Desideri proteggere il messaggio in modo che i dispositivi esterni alla rete non siano in grado di recuperare i contenuti dalla rete o di modificarli.
Il timestamping non è una soluzione completa da solo poiché, per definizione, ci sarà una finestra (anche se piccola) in cui il messaggio deve essere accettato. Gli altri nodi devono verificare che "ora" non sia successiva all'ora X dopo che è stata generata, ma X deve essere diverso da zero (in modo che il messaggio reale possa arrivare).
[C'è un altro tipo di problemi nel mantenere gli orologi sincronizzati su una rete distribuita, che richiederà un margine extra nel campo]
Il messaggio con data e ora sarebbe "È $ DATE. Chi ha il file A? Per favore, mandamelo. "Semplicemente aggiungere un HMAC al messaggio non lo proteggerebbe.
All'interno di quella finestra temporale ridotta, un altro nodo potrebbe anche inviare
“It's $DATE. Who has file A? Please send it to me.”
(copia dello stesso HMAC), quindi non è chiaramente sufficiente.
Tuttavia, se stai includendo chi sei nel calcolo, è diverso (potrebbe essere aggiunto implicitamente o semplicemente indicato nel messaggio): "È $ DATE. Sono il 10.10.10.10. Chi ha il file A? Si prega di inviarlo a 10.10.10.10 alla porta 9000. "
Tuttavia, devi anche proteggere la risposta in modo che la tua risposta provenga effettivamente da un nodo malvagio. Ad esempio, la comunicazione sulla porta 9000 potrebbe iniziare con:
“I am 10.10.10.12 connecting to 10.10.10.10. I do have file A you asked for at $DATE. It is 123 bytes long and has SHA256 aabbccdd…” || HMAC
Se il nodo non ha richiesto il file A a $ DATE, o se il contenuto del file non corrisponde all'hash specificato, dovrebbe eliminare ciò che ha ricevuto.
Un utente malintenzionato potrebbe duplicare la richiesta (o potrebbe essere duplicata dalla rete), rendendo potenzialmente 10.10.10.12 inviare le stesse informazioni a 10.10.10.10 molte volte. Potrebbe filtrarlo in base all'intestazione della richiesta mostrata sopra, ma è meglio fornire un identificatore per differenziare le risposte duplicate, per rispondere a una query ripetuta (ad esempio, il nodo di interrogazione potrebbe leggere continuamente lo stesso file, perché cambierà a breve ).
“This is query 987654 at $DATE. I'm 10.10.10.10. Who has file A? Please send it to 10.10.10.10 at port 9000.” || HMAC
Il nodo di interrogazione dovrebbe semplicemente ricordare le query inviate nell'ultimo periodo di tempo 2 * X approssimativamente e contrassegnare come In corso / Completato secondo necessità. Qualsiasi risposta che non corrisponde a una query in sospeso potrebbe essere scartata.
(Preferibilmente, l'identificatore sarebbe casuale, sebbene l'HMAC ti protegga dallo spoofing della risposta)
A questo punto, l'integrità dei messaggi è protetta dal segreto HMAC e tu sei protetto dai replay, potresti inviare le query in broadcast in modo abbastanza sicuro.
Tuttavia, dovrei notare che la rete si basa su un segreto condiviso tra i nodi. Cosa succederebbe se uno di loro fosse compromesso?
Un approccio più robusto sarebbe utilizzare chiavi asimmetriche su ciascun nodo. Fondamentalmente, si creano le chiavi per ogni nodo e una CA locale che firma ciascuno di essi. Archivia sui nodi una copia della chiave pubblica della CA e un elenco iniziale di revoca-vuoto.
Modifica i messaggi di cui sopra per sostituire l'operazione HMAC(message, secret)
con SIGN(message) || MyPublicKey
e fai in modo che i tuoi nodi si fidino del messaggio se viene firmato correttamente da una chiave firmata dalla CA locale e non dall'elenco di revoche.
(Puoi ignorare l'elenco di revoche se preferisci sostituire la CA -e le chiavi pubbliche firmate da essa- nel caso in cui una chiave sia stata compromessa)