Inizializzazione

Problema: far stabilire in modo sicuro una chiave tra centralina e sensore senza usare sistemi a chiave pubblica troppo pesanti.

Considerazioni sparse e/o di interesse quasi esclusivamente "storico"

Possibili soluzioni:

  • Un sistema "banale" (ma di implementazione non così banale come potrebbe apparire) può essere l'uso di un bus separato (nelle immediate vicinanze della centralina, o addirittura al suo interno per sfruttarne le caratteristiche elettromeccaniche) per la sola "caratterizzazione" dei controller dei nodi. La difficoltà è evitare che con strumenti tipo "TEMPEST" un attaccante esterno possa intercettare proprio la fase critica. Purtroppo questo lascia all'installatore ed al costruttore la possibilità di "sniffare" la chiave di ogni sensore, se ha potuto mettere le mani nella centrale prima della messa in servizio la situazione è già molto compromessa... Tra l'altro ho scoperto che una variazione di questo sistema viene (o veniva) usata dai militari con la "fillgun", in pratica una "pistola" che "sparava" in modo sicuro la chiave dentro ogni "nodo" (ovviamente tamper-resistant secondo standard militari)...
  • Usare DH, stabilendo "per standard" i valori di p (modulo, un numero primo) e g (generatore), che sono entrambi valori piuttosto critici per il sistema. L'unico problema serio che si può presentare è un attacco del tipo "man in the middle" che però richiederebbe l'attaccante già "in posizione" al momento dell'installazione (per esempio l'installatore). E quindi anche DH non pare risolvere completamente il problema.
  • Usare lo schema di Shamir a 3 passaggi, che purtroppo però richiede un cifrario a chiave simmetrica che sia commutativo e che non permetta di ricostruire Ka da {M}Ka, {{M}Ka}Kb e {M}Kb (questo esclude one-time-pad e la semplice moltiplicazione modulo-n, lasciando solo il medodo di Massey-Omura o quello di Robert Durnal). La complessità matematica è analoga a DH, quindi non pare interessante.
  • Sistemi basati su curve ellittiche, che però richiedono comunque calcoli piuttosto pesanti e complessi, anche se su numeri MOLTO più piccoli che in RSA o DH
  • NTRU public-key cryptography... Usa dei polinomi invece di "semplici" numeri... alla fine mi pare solo di poco più leggera di altri sistemi a chiave pubblica
  • Usare TPM e sincronizzarle, come indicato dai lavori di Karter, Kinzel ed altri sulla sincronizzazione di reti neurali in generale e di TPM in particolare). Questo sistema pare essere MOLTO leggero a livello computazionale, ma richiede di cambiare spesso la chiave (probabilmente non regge ad un attacco prolungato)
  • Usare il sistema di Maurer per il key agreement su canale pubblico (vedi anche una bella demo in Java)

Gli ultimi due metodi sono quelli che mi piacciono di più, dato che sono basati su metodi della teoria dell'informazione e non su problemi matematici PRESUNTI difficili (se domani qualcuno scopre un modo per fattorizzare o estrarre logaritmi discreti, BUM! certo che se nessuno è riuscito a fare di meglio negli ultimi secoli è difficile che ci riesca proprio ora... ma se i calcolatori quantistici iniziano a funzionare, gli algoritmi per scardinare velocemente molti algoritmi sono già disponibili!). Il rischio è che, trattandosi di campi di ricerca piuttosto nuovi, si scopra qualcosa in grado di minare le fondamenta del sistema da un momento all'altro (come farebbe un algoritmo veloce di fattorizzazione ad RSA).

Dopo un rapido scambio di mail col Prof. Dr. Ueli Maurer (che ringrazio moltissimo per la disponibilità e la velocità di risposta nonostante gli impegni) ho dovuto purtroppo accantonare il suo metodo: se l'attaccante ha accesso error-free al link "satellitare", allora può essere provato che è impossibile stabilire una chiave sicura tra Alice e Bob. A questo punto rimane solo la sincronia di reti neurali o TPM...

Dopo un altro scambio di mail, questa volta con Andreas Ruttor (che ringrazio calorosamente) riguardo la sua tesi, pare che la sincronizzazione di TPM sia un'ottima strada da seguire. Purtroppo sincronizzare due TPM richiede lo scambio di grosse quantità di dati tra i nodi (nell'ordine dei megabyte). Le formule per calcolare il tutto sono fornite nella tesi, ma vedo di inserire una tabella riassuntiva.

Dato ciò che è stato confermato dall'analisi di Andreas Ruttor, scegliamo K=3 (e la random-walk rule per l'aggiornamento dei pesi delle reti, così evitiamo il rischio del majority flipping attack, che funziona bene solo se si utilizza la Hebbian learning rule):

Quote:
For K = 3 synchronization time increases proportional to L2, but the success probability of any known attack decreases exponentially with increasing L. Consequently, L is a parameter similar to the key size in other cryptographic algorithms.

Inoltre:
Quote:
These results show that K = 3 is the optimal choice for the cryptographic application of neural synchronization. K = 1 and K = 2 are too insecure in regard to the geometric attack. And for K > 3 the effort of A and B grows exponentially with increasing L, while the simple attack is quite successful in the limit K → ∞. Consequently, one should only use Tree Parity Machines with three hidden units for the neural key-exchange protocol.

Ovviamente, per avere una sicurezza paragonabile ad una chiave simmetrica di Ns bit, Pe (la probabilità che l'attaccante si sincronizzi al 98% con A prima di B) deve essere minore di 2-Ns.

Si può quindi utilizzare la formula per K=3, N=1000: P(t_sync > S ) = 1-exp(-exp((42.6*L2-S)/(9.6*L2))) per calcolare il numero di passi per ottenere una sincronizzazione nel 90% dei casi (se non sincronizzo, butto tutto e ricomincio).

Inoltre, per non dover trasmettere tutti i dati, uso la sincronizzazione in due fasi: nella prima fase (bassa sicurezza) sincronizzo su canale "pubblico" (può essere intercettato da E) due TPM che generino ALMENO 2256 possibili chiavi (ovvero (2L+1)NK>2256, quindi sono sufficienti L=3, K=3, N=100 che forniscono 7300 possibili chiavi ma si sincronizzano in meno di 500 passi), poi uso queste due TPM per generare gli ingressi per la sincronizzazione (sicura) delle altre due TPM, usando il canale pubblico per il solo scambio dei pacchetti di sincronizzazione.

Se E riuscisse a sincronizzarsi con A1 prima di B1, allora per lui sarebbe come se la sincronizzazione di A2 e B2 avvenisse su canale pubblico (Pe< 2-Ns), altrimenti dovrebbe tirare ad indovinare (Pe=2-Ns).
In pratica, il migliore attacco al sistema, per E, è di tirare ad indovinare la chiave finale, senza neanche tentare di intercettare il canale. E se si considera Ns=256, allora anche il NIST ritiene le chiavi sicure per alcuni decenni (almeno se chi tenta di indovinare non è troppo fortunato...).

Un'altra idea è considerare un perimetro di sicurezza diverso: l'intera centralina invece del suo solo processore per le comunicazioni. Sembra banale, ma ha una conseguenza molto importante: possiamo effettuare uno scambio chiavi in chiaro!!!
Infatti non abbiamo più da preoccuparci di quale parte della centralina possa essere compromessa: o è integra nel suo complesso o lo scambio delle chiavi può essere insicuro, indipendentemente dal metodo usato. A quanto pare il sistema militare della fillgun non è così stupido come può sembrare Smile
Il "contro" è che (come in tutti i metodi "a contatto") richiede che tutte le centraline siano posizionate all'avvio iniziale, pena la necessità di effettuare un redeploy COMPLETO del sistema (altrimenti la prima centralina dovrebbe passare dei dati sicuri alla seconda, ma se la prima è compromessa, l'attaccante può conoscere tutte le chiavi usate dai sensori!).

Da valutare, eventualmente, una vera fillgun: una "pistola" con cui caricare le chiavi nei sensori prima e nella centralina poi. Bisogna però valutare bene eventuali attacchi TEMPEST e il caso di furto/alterazione della fillgun.
Uno scenario di aggiunta centralina su infrastruttura esistente potrebbe essere, in questo caso:

  1. Viene comunicato alla centralina funzionante che si inizia l'operazione (per sapere come "trattare" i messaggi di allarme che verranno generati)
  2. Le viene "presentato" il modulo di comunicazione della seconda centralina, come se fosse un normale nodo
  3. Il modulo di comunicazione della seconda centralina viene inserito nella fillgun, diventando praticamente una "centralina mobile"
  4. Per ogni nodo, all'apertura (quando scatta l'anti-tamper) deve seguire, entro pochi secondi (max 30, indicativamente -- più che sufficienti per un "apri scatola, connetti plug, attendi conferma, disconnetti plug, chiudi scatola"), un messaggio autenticato della fillgun che comunica l'avvenuta aggiunta della chiave (senza rivelare QUALE chiave ma solo un ID!)
  5. Alla prima interrogazione, anche il sensore indicherà che ha aggiunto la chiave con l'ID dato
  6. La centralina confermerà al sensore che la chiave è valida
  7. Quando il modulo della nuova centralina verrà tolto dalla fillgun ed inserito al suo posto, comunicherà all'altra centralina che è pronto ad operare normalmente
  8. Finalmente la nuova centralina, ricevuta conferma dalla vecchia, potrà iniziare ad interrogare i sensori con le proprie chiavi

I messaggi dei sensori devono comunque essere autenticati, e questo è un metodo interessante:

  1. Il sensore genera un ID univoco, un messaggio (per es. il nome del produttore e il modello) ed un valore casuale (X, tenuto temporaneamente segreto) per il chaining dell'autenticazione
  2. Alla centralina viene fornito (al momento della presentazione) l'ID del sensore e H(ID, messaggio, H(X)) [H è la funzione di hash]
  3. Il sensore trasmette periodicamente in broadcast (ID, H(ID, X, stato, H(X')))
  4. Le centraline confermano la ricezione
  5. Il sensore trasmette ad ogni centralina il messaggio in chiaro (ID, X, stato, H(X'))
  6. Ogni centralina verifica la corrispondenza tra i valori degli hash ricevuti e quelli calcolati sui messaggi
  7. Se c'è discordanza sugli hash o il messaggio segnala un allarme, suona le campane del giudizio! Smile

[Questo schema di autenticazione è descritto in questo lavoro di Ross Anderson ed altri (di cui consiglio un'attenta lettura), eventuali errori li ho sicuramente inseriti io].
Ovviamente anche le risposte delle centraline possono essere autenticate nello stesso modo. Ed invece di un hash si può usare una funzione crittografica, rivelando al secondo passaggio la chiave.
È importante che i sensori non resettino mai lo stato della catena (altrimenti un attaccante potrebbe inserirsi ed escludere il sensore, dato che già conosce la preimmagine della chiave da usare).
Eventuali altre centraline possono unirsi al sistema in un secondo tempo solo sfruttando la "transitività" della fiducia (circa come avviene in PGP): la nuova arrivata deve fidarsi dello stato che le viene passato dalle "vecchie" o semplicemente "imparando" dalle loro risposte.
Questo protocollo richiede l'uso di pacchetti di lunghezza variabile. Ipotizzando un hash a 128 bit (16 byte) ed indirizzi a 64 bit (8 byte), si hanno pacchetti dai 32 byte in su (in funzione della lunghezza dei messaggi.
E oltretutto prevede che i messaggi siano "loggati" e che un attaccante non possa ritardarli.
Un problema è la possibilità, da parte del costruttore o dell'installatore, di fornire un chip opportunamente "truccato" (l'autenticazione funziona solo una volta: l'attaccante può creare un secondo chip usando la prima risposta del chip originale che rivela la preimmagine dell'hash). L'unico modo per tutelarsi da questo è l'autoprogrammazione dei chip.

Questo metodo, facendo passare i messaggi in chiaro, permette la presenza di nodi "di monitoraggio" completamente passivi (di cui anche le centraline non sanno nulla) aggiunti in qualsiasi momento.

Probabilmente, la cosa migliore sarà un uso parsimonioso della crittografia asimmetrica, affiancato ad un uso pesante di quella simmetrica.

E che dire dell'uso di ECC (crittografia su curve ellittiche)? In base alle considerazioni fatte alle pagg. 76-81 di questa tesi (dati in parte confermati/presi dal sito della NSA) dovrei proprio considerarle! Ed è quanto ho fatto, anche perchè, a quanto dice, DH a 768 bit non è da considerare sicuro già ora! Per quanto ciò suoni troppo allarmistico (non mi risultano logaritmi discreti calcolati per più di 120 cifre decimali, circa 400 bit... io ne userei almeno 768), voglio che il sistema che sto progettando sia quanto di più robusto sia possibile ottenere (a costi sufficientemente contenuti).

Il NIST DSS Standard fornisce i parametri (validati!) di parecchie curve.

La seguente tabella, ricavata unendo i dati della tesi e quelli del documento del NIST sopracitati, dovrebbe aiutare:


Symmetric-key bits Validità (NIST SP 800-57) Symmetric-key reference algorithm RSA/DH bits (DLP) ECC bits (ECDLP in GF(p)) ECC bits (ECDLP in GF(2^m))
80 2010 Skipjack 1024 192 163
112 2011-2030 3DES 2048 224 233
128 2030+ AES-128 3072 256 283
192 Non indicata AES-192 7680 384 409
256 Non indicata AES-256 15360 521 571

La riga che mi interessa implementare è l'ultima, ovvero, usando la curva NIST p521 (o NIST b571), ho una chiave considerabile sicura BEN OLTRE il 2030 anche per impieghi militari (almeno fino al livello 'classified', non 'secret')!

Il problema, con le curve ellittiche, è la parte relativa ai calcoli:

Quote:
Abstract. This paper explains the design and implementation of a high-security elliptic-curve-Diffie-Hellman function achieving record-setting
speeds: e.g., 832457 Pentium III cycles (with several side benefits: free key compression, free key validation, and state-of-the-art timing-attack
protection), more than twice as fast as other authors’ results at the same conjectured security level (with or without the side benefits).
(da "Curve25519: new Diffie-Hellman speed records", Daniel J. Bernstein)

Quindi su PIC diventa completamente improponibile. Ho anche trovato un lavoro ("ELLIPTIC CURVE CRYPTOGRAPHY ON SMART CARDS WITHOUT COPROCESSORS" di Woodbury, Bailey e Paar) molto interessante, ma che mi toglie 'quasi' ogni speranza di poter efficacemente usare ECC invece di altri sistemi a chiave pubblica: "We show that an elliptic curve scalar multiplication with a fixed point [...] can be performed [...] in less than 2 seconds". Visto che ogni operazione sulle curve implica almeno una moltiplicazione scalare, e che hanno considerato ECC a 132 bit ("equivalenti" ad una chiave segreta di 72 bit), si può concludere che PER IL MOMENTO lo scambio di chiavi con ECC è improponibile, a meno di non ricorrere a micro parecchio più potenti (e costosi!). Ma un altro lavoro ("Comparing Elliptic Curve Cryptography and RSA on 8-bit CPUs") mi indica 2.19s per ECC secp224r1 usando 422byte di RAM e 4812byte di codice su un ATmega128 ad 8MHz (dato che i nuovi ATmega128 arrivano a 16MHz, ed altri modelli anche a 20, posso ottenere un calcolo ECC-224 (con sicurezza equivalente a 112bit) in circa 1s con un chip che costa circa 12.60$). Abbastanza abbordabile, ma non ancora sufficiente.

Ovviamente, se qualcuno ha dei riferimenti per potermi contraddire non mi arrabbio! Anzi, mi farebbe molto piacere!

Altrettanto ovviamente, visto che il sistema è modulare, chi richiede una sicurezza superiore a quella offerta da DH-768 potrà dotarsi di moduli di comunicazione con chip più "dotati", ed in grado, quindi, di gestire in tempi ridotti anche i calcoli necessari per ECC a 521 o più bit.

La valutazione definitiva la farò a breve, appena implementate le mie routine di esponenziazione modulare sul PIC18F4620 (che ho disponibile, e che mi permette di implementare (senza ottimizzazioni troppo spinte per l'utilizzo della RAM) anche DH-3072 (sicurezza circa equivalente a 128 bit di chiave segreta, quindi perfetta per gli algoritmi che intendo usare). Sarebbe inutile infatti scartare ECC perchè troppo lenta, e poi trovarmi con DH altrettanto lento!

Il numero primo da usare come modulo per DH sarà uno dei seguenti:

2560-bit secure Diffie-Hellman modulus #1
This is adequately-sized to support 128-bit generations at full strength.

b8eb857df1eb89bc8c13ef777772d6f3d3716ecc671e5dfbb969c28ffc2c3383
283b54ca857ec4fff0cf45badd491e1203918b1d35ee197cafc039f65654e908
d0235537b280a605d902a3e273362cb21ba61423b926a57f41864195f785d8c2
8524345bfb89a05490ea1a56207db04a958590b1725ef2b538a05bb833ebbe0d
fb55f8195ae050ad216739970344c1423ac016cdc501dc6e51af56bfedb247e7
460530c6b5a73046b448818d85f19a5af50c19fa03143b108b71b18081b80e9a
8c5648cf8d2772f2e81c44f479fcf483db3b5e68d906833278de670cfdce7023
0c88beded782940e9724d1269412223f1bf70445288612b36fa67abf2f4dd391
1173c08793c42e51b2f469ac3455a894cb15dbc870c1252fca298a24cd5e507d
b637960f6eeb653d971075b73dfae5a60c51314313a6815438f1c6b4a6f3a2cf

3072-bit secure Diffie-Hellman modulus #1
Unknown strength greater than 128-bit, less than 192-bit.

c48f6e2843518c51000efb2aa67017951bca4b322b94c0ea1bb3f47444aa47a4
1b26ef9f4b0566c7c503ae38e53260127d1110c97c4d84746c49e74ddfcce99e
9dabe0588cdde430bacbce373da1adc4826fba83dc121798b4182d06398336ff
ed5149e893a22a17d341833693cc8c07b953a5f88abca6ce4ebbb33712406d37
0ae0dcbd55f3bd3b7fc1d15f2fa384cab5e10115aa342d00e04ff76d12c21059
35aa6867881384144d2affeaa9bec900e2ab7a24907c0129451531d5efca29d4
07bea207a4534ab45d5541fe5e248a9280b8e01e84d48570942c05137fc888ca
6b9b7e96be659352149ce05a0754cba3a22ce47da03deba945f2d5123a3fc02a
e46300ee8791ee6a6bba15d92f9ad0895811b277ac20becee88ea33a2e18ec3b
5ce8e913aa85c2912e214190eb6a1ceef052288c95fe94988b2e36c74b384d4e
26eb1e8fdb1c3898695c97ca1114207bd69fcf9ecbec36cae0092e20dcfbbbbd
6169970e2ec2309c178b0907d9bad5c0c9a41b9abfa997306404777836b22acf

(Da "Sophie Germain Primes for Diffie-Hellman Key Exchange", che riporta alcuni primi di SG fino a 8192bit!
Altri (purtroppo espressi in decimale, quindi più laboriosi da inserire nella ROM del micro) possono essere reperiti, insieme alla relativa prova di primalità e alla prova di essere di SG, su questo sito, a cura di Tero Kivinen.

Un metodo per ridurre le possibilità di un attacco MITM quando si usa DH è tenere conto del tempo (per esempio aspettando per un determinato -breve- intervallo una risposta che indichi la conoscenza della chiave appena stabilita) e fornire all'utente un feedback visivo di quando stanno venendo memorizzate chiavi nei moduli (per es. accendendo un LED all'inizio della fase di handshake e spegnendolo quando la chiave è stata memorizzata). In questo modo quando l'utente avvia la programmazione può verificare che entrambi i moduli stiano lavorando contemporaneamente. Un attaccante deve disporre di una potenza di calcolo almeno doppia per poter portare avanti i due protocolli in parallelo e terminarli nel massimo tempo previsto. Una attenta taratura delle temporizzazioni potrebbe rendere molto complesso anche l'uso di un ricetrasmettitore (che introduce una certa latenza).

Proposta v1.0

Giusto per porre le basi... Dovrebbe essere ben funzionante, ma ancora non mi piace del tutto... In particolare è piuttosto vecchia e non tiene conto di alcune considerazioni fatte in seguito.

Dato che il discorso rischia di farsi molto ingarbugliato, meglio dare qualche definizione:


A,B

Centraline

M

Modulo di comunicazione (anche: "sensore")

Kxy

Chiave tra X ed Y

E

Eavesdropper, Eve, insomma l'attaccante

P, C

Bus di comunicazione ("Presentazione" e "Comunicazione normale"). C è comune tra A e B, P è locale, quindi ci sono Pa e Pb); NON possono avvenire passaggi di dati tra P e C, se non da parte di A o B

E(K,X)

Cripta X usando K

h(X)

Calcola l'hash di X

Nxy

Contatore di messaggi spediti da X a Y

L'inizializzazione avviene così:

  1. Uso di DH sul bus P per stabilire Kam (== Kma se M appartiene ad un sensore, altrimenti ripetere su Pb per definire Kma!=Kam)
  2. Spostamento del sensore da P a C con scambio di messaggi di prova [DA DEFINIRE]

Se il sistema è fidato (E non è all'interno di A), non ci sono problemi. Se invece si ritiene che una centrale possa essere stata manomessa, si possono avere due casi:

  1. E intercetta solo P: non appena viene spostato M su C la comunicazione fallisce dato che viene a mancare la doppia traduzione Kme<->Kea, e quindi il gioco si scopre immediatamente
  2. E intercetta sia P che C: si rende necessaria una seconda centralina per smascherarlo

Se i seguenti assunti non fossero accettabili, si renderebbe necessario ripensare il sistema da capo:

  • Lo spostamento fisico di M costituisce un canale sicuro (può essere effettuato dall'utente)
  • Una sola centralina può essere stata manomessa (deve arrivare direttamente dal produttore ed essere sigillata; A e B vengono fornite da produttori diversi o viene realizzata "in proprio")
  • M difende le password memorizzate per un tempo sufficiente (anni se rimane in comunicazione su C, minuti se viene tolto da C): in questo modo non può venire sostituito da un M' diverso che utilizzi la stessa Kam e non è necessario difenderlo da attacchi sofisticati (spettrotermografia laser, pattern di assorbimento, ecc.)
  • M è integro: se non lo fosse, E potrebbe inviargli un comando del tipo "dimmi le password che stai usando" quando lo rileva su C, vanificando qualunque misura preventiva (si può ricorrere all'autoprogrammazione)

Attenzione al momento tra la rimozione di M da P e la sua messa in servizio su C: se viene "catturato" in questa fase (violando il primo assunto: lo spostamento da P a C è sicuro), E potrebbe impossessarsene e sostituirlo con un M' in cui va a programmare la stessa Kam di M. Se M viene rimosso da C quando ha già comunicato la sua presenza, invece, il tempo di difesa della chiave è sufficiente a far sì che A lo riconosca come un "taglio fili" (M non risponde) con la logica reazione (ed il rifiuto di riattivarlo se prima non ripassa da Pa, richiedendo quindi un'azione ATTIVA da parte dell'utente).

Quando si presenta (su Pb) a B un M già presentato ad A:

  1. Viene stabilita una chiave Kbm (==Kmb)
  2. Viene inviato su C E(Kba, M|Nba|h(Kma))
  3. A risponde con E(Kab, n|Nab) ; n è un numero casuale con parità pari se "OK", dispari se "BAD"

È necessario avere Kab != Kba per evitare che E da una centralina possa decriptare (e falsificare) tutti i messaggi.

Analizziamo il caso in cui E intercetti C e Pa:

  • In A Mb stabilisce con Ma Kba [in realtà Mb memorizza Kbe e Ma memorizza Kea]
  • Si rimette Mb in B; si sposta Ma in B
  • In B Ma stabilisce con Mb Kab [e questa E non la può conoscere, dato che si trova in A!]
  • Si rimette Ma in A
  • Ma invia E(Kab, A|h(Kba))
  • Mb riesce a decriptare il messaggio, ma non verifica h(Kba) (la confronta con h(Kbe)) => FAIL

Analizziamo il caso in cui E intercetti C e Pb:

  • In A Mb stabilisce con Ma Kba [E questo non lo conosce]
  • Si rimette Mb in B; si sposta Ma in B
  • In B Ma stabilisce con E (che si spaccia per Mb) Kae, mentre E stabilisce con B Keb
  • Si rimette Ma in A
  • Ma invia E(Kae, A|h(Kba))
  • E "traduce" il messaggio in E(Keb, A|h(Kba)) [nota che non può alterare h(Kba) dato che non conosce Kba]
  • B verifica h(Kba), quindi invia E(Kba, B|h(Keb))
  • E deve limitarsi a ritrasmettere il pacchetto, dato che, non conoscendo Kba, non è in grado di interpretarlo
  • A riceve e decodifica, ma non verifica h(Kbe) dato che tenta di confrontarlo con h(Kea) => FAIL

Quindi (se non ho sbagliato l'analisi), con l'uso di due centraline e sotto le ipotesi iniziali, il sistema è sufficientemente robusto da tollerare un attacco con PESANTE violazione di una centralina prima della messa in opera (E è il costruttore o l'installatore).
Da notare che il sistema segnala l'anomalia anche se le due centraline sono state compromesse da individui diversi (Ea ed Eb non comunicano tra loro).

Per stabilire la chiave segreta su P utilizziamo, come detto al punto 1, DH. Per semplificare il firmware e minimizzare l'uso di RAM (sempre piuttosto scarsa nei micro...), fissiamo "per standard" P (che deve essere primo e della forma P=2Q+1, con Q primo di Sophie Germain [DA DEFINIRE]) di 768 o 1024 bit, e g (2, 3 o 5 sono valori usati piuttosto spesso).
Quando viene iniziata la sequenza di presentazione, la centrale deve "concedere" un po' di tempo (max 2 secondi) al sensore per permettergli di accumulare entropia dall'RNG. Appena il sensore è pronto, spedisce X=ga (mod P). Ora la centralina spedisce Y=gb e calcola K=Xb. La stessa K viene calcolata dal sensore come K=Ya. Come chiave di comunicazione viene usato l'hash di K, così da avere una stringa binaria pseudocasuale di lunghezza opportuna.

Usando un PIC 16F87/16F88 (che dispone di ben 368 byte di RAM) posso gestire 'facilmente' l'esponenziazione modulare di numeri di max 768 bit (con qualche trucco dovrei poter gestire anche numeri di 1024 bit, fissando P in memoria programma invece che in EEPROM). Attualmente, per riuscire a calcolare il modulo discreto di un numero del genere, sono necessari vari anni di calcolo (se, come pare, fattorizzazione e logaritmo discreto sono circa "computazionalmente equivalenti" -anche se da quanto ho potuto vedere sembra che le costanti per il logaritmo siano più alte-, e dal 2005 nessuno ha ancora "avuto voglia" di vincere i 50K$ di premio per RSA-768 penso si possa concludere che un modulo DH di 768 bit 'vale più' di 100K$... probabilmente PARECCHIO di più, dato che per passare da 576 a 640 bit ci sono voluti 2 anni!). Inoltre tutto questo è per UN SINGOLO nodo di comunicazione (= un sensore, nell'ottica della massima paranoia, una stanza nell'ottica del risparmio).
Ovviamente, se possibile, preferisco implementare un sistema a curve ellittiche, dato il risparmio di memoria e l'incremento di sicurezza!