.. meta:: :language: it :description language=it: Distribuzione di chiavi pubbliche :description language=en: Public-key distribution :keywords: IT Security, public-key distribution :author: Luciano De Falco Alfano 05 Distribuzione di chiavi pubbliche =================================================== .. contents:: :local: La cifratura tramite chiavi pubbliche concorre a risolvere i problemi di distribuzione delle *session key*. A questo fine vi sono due aspetti importanti riguardo l'uso di chiavi pubbliche: * la loro distribuzione; * e il loro uso per distribuire *secret keys*. Per distribuire chiavi pubbliche si possono usare: * annunci pubblici; * directory disponibili pubblicamente; * autorità per le chiavi pubbliche (*public-key autority*); * certificati di chiavi pubbliche. Annunci pubblici -------------------- In questo caso l'utente invia la chiave pubblica ai destinatari, o la pubblica verso intere comunità. Ad es. si può appendere una chiave PGP ad un messaggio di email o postarlo su nuovi gruppi è email list. La minaccia maggiore per questo metodo è la **contraffazione** (**forgery**). Chiunque può creare e diffondere una chiave affermando di essere qualcun altro. E la falsa identità può essere utilizzata per attività malevole. Directory pubblicamente disponibile -------------------------------------- Si ha una maggiore sicureza registrando le chiavi in uuna directory pubblica. La gestione e la distribuzione della directory è affidata ad un entità di fiducia. Una directory di questo genere: * contiene record del tipo {nome, chiave pubblica}; * i partecipanti si registrano in modalità sicura (ad es. di persona); * i partecipanti possono cambiare chiave quando opportuno; * la directory viene pubblicata a cadenza regolare; * la directory può assere consultata elettronicamente. In questo caso il richio consiste nella eventualità che un attaccante possa ottenere la chiave privata del gestore della directory. In tal caso potrebbe pubblicare chiavi false e impersonare un qualunque partecipante. Public-key autority ---------------------- Anche in questo caso vi è una autorità centrale che mantiene una directory di chiavi pubbliche di tutti i partecipanti. Inoltre i partecipanti conoscono la chiave pubblica dell'autorità centrale. L'interazione è come segue: .. image:: ./images/05_public_key_authority.svg 1. *A* richiede non cun messaggio, dotato di timestamp :math:`T_1`, la chiave pubblica di *B*; 2. l'autorità risponde ad *A* con un messaggio criptato con la propria chiave privata [#]_; il messaggio contiene: la chiave pubblica di *B*, la richiesta originale [#]_, il timestamp originale [#]_; 3. *A* memeorizza la chiave pubblica di *B* e la usa per cifrargli un messaggio contente l'identificativo di *A* e il *nonce* :math:`N_1` per identificare il messaggio inviato; 4. e 5. *B* richiede all'autorità la chiave pubblica di *A* con la stessa procedura seguita da *A*; ora *A* e *B* hanno le rispettive chiavi pubbliche e possono cominciare la conversazione, ma, per evitare la possibilità di *reply* si usano altri due passaggi: 6. *B* invia un messaggio ad *A* criptato con chiave pubblica di *A*, contenente il *nonce* :math:`N_1` ricevuto e un nuovo *nonce* :math:`N_2` generato da *B* [#]_; 7. *A* risponde a sua volta con :math:`N_2` criptato con la chiave pubblica di *B* [#]_. Questo scenario ha un paio di problemi: * richiede accesso online alla directory della authority; * la authority può divenire un collo di bottiglia ed essere vulnerabile ad attacchi malevoli. Certificati di chiavi pubbliche --------------------------------- Per evitare i problemi predetti si può ricorrere ai **certificati**. Questi permettono lo scambio di chiavi senza la presenza online dell'authority. Un certificato lega **l'identità** ad una chiave pubblica. E può contenere altre informazioni, come un periodo di validità, diritti d'uso ... Il legame tra identità e chiave è eseguito da una *autorità di certificazione* che **firma** il certificato. Il certificato può essere verificato da chiunque conosca la chiave pubblica dell'autorità. Il certificato viene prima generato, e successivamente utilizzato, come indicato qui di seguito: .. image:: ./images/06_public_key_certificate.svg * Ogni partecipante richiede il proprio certificato alla *certificate authority*, forneno la propria chiave pubblica (:math:`KU_A` e :math:`KU_B`); la richiesta deve avvenire con modalità tali da permettere l'identificazione del richiedente; * l'autorità consegna al richiedente il certificato, criptato con la chiave privata dell'autorità; ad es. *A* otterrà :math:`C_{A} = E(KR_{auth}, [T || ID_{A} || KU_{a}])`, dove :math:`KR_{auth}` è la chiave privata dell'autorità, *T* è un timestamp, e :math:`ID_A` è l'identificativo di *A*; * analogamente il certificato per *B*; * a questo punto chiunque riceva un certificato (messaggi 1 e 2 nella figura precedente) può decrittarlo utilizzando la chiave pubblica dell'autorità (:math:`PU_{auth}`) utilizzando :math:`D(PU_{auth}, C_{A}) = D(PU_{auth}, E(KR_{auth}, [T || ID_{A} || KU_{a}])) = (T || ID_{A} || KU_{a})` Si osserva che: * il fatto che il certificato sia decrittabile con la chiave pubblica dell'autorità, assicura che sia stato emesso da essa; * la presenza di :math:`ID_A` e :math:`PU_A` nel certificato fornisce al destinatario del certificato i mezzi per comunicare con il mittente e la sua identificazione; * la presenza del timestamp *T* serve a contrastare lo scenario in cui un attaccante riesca ad ottenere la chiave privata dell'utente; in tal caso l'attaccato può generare una nuova coppia di chiavi pubblica e privata, e richiedere un nuovo certificato; in questo caso il nuovo timestamp serve come data di scadenza del precedente certificato. Utilizzo di *public-key* per la distribuzione di *secret keys* --------------------------------------------------------------- Non si utilizzano le chiavi pubbliche per criptare la comunicazione perché sono algoritmi impegnativi, che rallenterebbero il data rate. Invece vengono utilizzate per distribuire *session key**, tipicamente chiavi simmetriche. Di seguito alcuni protocolli per la distribuzione di *session key*. **Distribuzione semplice di secret key**. Proposta da Merkle nel 1979, si svolge come rappresentato qui di seguito. .. image:: ./images/07_simple_secret_key_distribution.svg In questo caso, se *A* vuole comunicare con *B*: 1. *A* genera una coppia di chiave pubblica/privata (:math:`PU_A`, :math:`PR_A`) e invia a *B* un messaggio con la sua chiave pubblica e il proprio identificativo :math:`ID_A`; 2. alla ricezione del messaggio, *B* genera una chiave segreta simmetrica (:math:`K_s`), e la trasmette ad *A* criptandola con la sua chiave pubblica. A questo punto *A* e *B* si possono parlare utilizzando :math:`K_s`. Questo protocollo non è sicuro per attacchi del tipo *man-in-the-middle*. Un opponente può intercettare il messaggio in (1), sostituirvi una propria chiave pubblica, ed intercettare la relativa risposta (2), decrittarla scoprendo la chiave :math:`K_s` e ricostruire il messaggio (2) con la chiave pubblica originale :math:`PU_A`. Dopo di che si può mettere in ascolto della successiva conversazione scambiata utilizzando :math:`K_s`. **Distribuzione di secret key con confidenzialità e autenticazione**. Proposta da Needham nel 1978, si svolge come segue. .. image:: ./images/08_confidentiality_secret_key_distribution.svg Qui, partiamo dal presupposto che *A* e *B* si siano scambiate le loro chiavi pubbliche [#]_. Dopo di che: 1. *A* usa la chiave pubblica di *B* [#]_ per criptare e inviargli un messaggio contenente un proprio identificativo (:math:`ID_A`) e il *nonce* :math:`N_1` che identifica la transazione; 2. a sua volta *B* risponde con un messaggio criptato con la chiave pubblica di *A*, che contiene il *nonce* di *A* [#]_ e un secondo *nonce* (:math:`N_2`), generato da *B*; 3. a sua volta *A* rimbalza :math:`N_2` verso *B* criptando con la chiave pubblica di *B* [#]_; 4. inoltre *A* sceglie una chiave segreta simmetrica :math:`K_s`, la cripta con la propria chiave privata :math:`PR_A` [#]_ e la invia a *B* dopo avere criptato con la chiave pubblica di *B*. Questo protocollo assicura la confidenzialità e l'autenticazione del mittente. Scambio di chiavi secondo Diffie-Hellman ----------------------------------------- Il primo schema a chiave pubblica (public key) non secretato [#]_ è stato proposto da Diffie & Hellman nel 1976 contemporaneamente alla esposizione dei concetti fondamentali. Si tratta di un metodo pratico per scambiare pubblicamente una *secret key*, ed è utilizzato in vari prodotti commerciali. Vi è una fase di **setup**, * in cui gli utenti concordano i parametri globali: * :math:`q` un numero primo grande o polinomiale; * :math:`\alpha` una radice primitiva :math:`mod \; q` [#]_; * ogni utente genera le proprie chiavi: * sceglie un numero come chiave segreta (:math:`x_A < q`); * calcola la propria chiave pubblica (:math:`y_{A} = \alpha^{x_{A}} \; mod \; q`); * ogni utente rende pubblica la chiave :math:`y_A`; * la chiave di sessione condivisa per gli utenti A e B è :math:`K_{AB}`: .. math:: K_{AB} &= \alpha^{x_{A} \cdot x_{B}} \; mod \; q \\ &= y_{A}^{x_{B}} \; mod \; q \quad \text{(che B può calcolare)} \\ &= y_{B}^{x_{A}} \; mod \; q \quad \text{(che A può calcolare)} Dopo di che: * :math:`K_{AB}` è usata come *session key* nella cifratura privata tra *A* e *B*; * se *A* e *B* comunicano nuovamente, hanno la stessa chiave, a meno che decidano di cambiare le loro chiavi pubbliche; * un opponente può vedere solo :math:`\alpha`, :math:`q`, :math:`y_{A}`, :math:`y_{B}`, e dovrebbe risolvere l'equazione :math:`y_{A} = \alpha^{x_{A}} \; mod \; q` per trovare la chiave segreta :math:`x_{A}`. Ad **esempio**, gli utenti *A* e *B* desiderano scambiarsi le chiavi: * concordano sul primo :math:`q = 353` e :math:`\alpha = 3`; * selezionano le random secret keys: :math:`x_{A} = 97`, :math:`x_{B} = 233`; * calcolano le chiavi pubbliche: * :math:`y_{A} = 3^{97} \; mod \; 353 = 40`; * :math:`y_{B} = 3^{233} \; mod \; 353 = 248`; * calcolano la shared session key come: * :math:`K_{AB} = y^{x_{A}} \; mod 353 = 248^{97} \; mod 353 = 160`; * :math:`K_{AB} = y^{x_{B}} \; mod 353 = 40^{233} \; mod 353 = 160`; **Vulnerabilità del protocollo Diffie-Hellman**. Questo protocollo è vulnerabile ad attacchi del tipo *man-in-the-middle*. Infatti un opponente *D* può preparare due coppie di chiavi pubbliche/private ed utilizzarle per sostituirle alle chiavi di *A* e *B* nelle relative comunicazioni. In pratica la comunicazione :math:`A \leftrightarrow B` diviene :math:`A \leftrightarrow D \leftrightarrow B` in cui *D* gioca il ruolo di gateway dei messaggi tra i due partecipanti originari, potendo effettuare evesdropping o alterando i messaggi a suo giudizio. Per evitare questo tipo di attacco è necessario introdurre l'autenticazione dei partecipanti alla conversazione. Cosa che viene fatta nel caso di protocollo di scambio chiavi tramite certificati. ----------------- .. [#] Questo assicura che è l'autorità ad inviare il messaggio. .. [#] Per rendere possibile la gestione del messaggio da parte di *A* nel caso abbia inviato più richieste, e il controllo che il messaggio non sia stato alterato prima di arrivare all'autorità. .. [#] Per controllare che non si tratti di una richiesta datata. .. [#] La presenza di :math:`N_1` assicura *A* che *B* sia il mittente. .. [#] In tal modo *B* è certo che *A* è il suo corrispondente. .. [#] Scambio di chiavi pubbliche che può avvenire con uno dei protocolli illustrati in precedenza: *public key authority* o *certificate*. .. [#] Quindi solo *B* la può decrittare utilizzando la sua chiave privata :math:`PR_b`. Questo esclude attacchi del tipo *man-in-the-middle*. Si consideri questo aspetto nel seguito: tutti i imessaggi sono criptati con chiave pubblica; di conseguenza possono essere decrittati solo dal partecipante con la giusta chiave privata. .. [#] La presenza di :math:`N_1` assicura *A* che il corrispondente è *B*. .. [#] La presenza di :math:`N_2` assicura *B* che il corrispondente è *A*. .. [#] Questo serve per identificare *A* come autore della chiave segreta. .. [#] Ora si sa che James Ellis dell'ufficio CESG (Gran Bretagna) propose lo stesso concetto alla sua organizzazione nel 1970, in una relazione tenuta segreta. .. [#] Se :math:`\alpha` è una radice primitiva :math:`mod \; q`, vale la seguente affermazione: :math:`\alpha \; mod \; q, \alpha^{2} \; mod \; q, \cdots \alpha^{q-1} \; mod \; q` sono :math:`q - 1` interi distinti.