Post on 16-Aug-2020
Lezione 5: Socket SSL/TLS
Corso di Programmazione in Rete
Laurea Magistrale in Ing. Informatica
Università degli Studi di Salerno
1
Outline
✦ Introduzione
✦ Gestione delle chiavi e dei certificati
✦ Comunicazione con socket SSL/TLS
2
Introduzione
✦ Mentre per applicazioni limitate a una rete locale si può assumere che il contesto sia “amichevole”, l’arrivo di Internet rende necessarie considerazioni sulla sicurezza della comunicazione• autenticazione dell’altro end-point con cui si
comunica
• riservatezza dei dati scambiati
3
Crittografia
✦ Le esigenze di sicurezza si risolvono adottando algoritmi di crittografia per proteggere le comunicazioni
✦ In particolare, la crittografia a chiave pubblica (detta anche a chiave asimmetrica) consente l’autenticazione dell’altro end-point senza il problema della condivisione della chiave
4
Crittografia a chiave pubblica
✦ Ciascuno dei due end-point genera due chiavi:• una chiave privata, che deve essere nota solo al
proprietario
• una chiave pubblica, che deve essere resa nota all’altro end-point
✦ I dati codificati con una chiave privata possono essere decodificati solo con la corrispondente chiave pubblica e viceversa
5
Crittografia a chiave pubblica
✦ Il mittente codifica due volte l’informazione:• con la propria chiave privata
• con la chiave pubblica del destinatario
✦ Il destinatario deve effettuare una doppia decodifica per leggere l’informazione:• con la propria chiave privata
• con la chiave pubblica del mittente
6
Crittografia a chiave pubblica
✦ Il mittente è certo che solo il destinatario leggerà i dati, perché è necessaria la chiave privata del destinatario per la decodifica (riservatezza)
✦ Il destinatario è certo che i dati sono stati inviati dal mittente, perché è necessaria la chiave privata del mittente per la codifica (autenticazione)
7
Crittografia a chiave pubblica
✦ In pratica, per motivi prestazionali, il client e il server usano questa tecnica per scambiarsi una chiave simmetrica in modo sicuro e poi passano a un algoritmo di crittografia tradizionale
✦ Spesso è necessaria la sola autenticazione del server; in tal caso solo il server ha una coppia di chiavi, e il client deve avere la chiave pubblica del server
8
Certificati
✦ Per evitare la necessità di scambiare in anticipo in modo sicuro le chiavi pubbliche, si usano certificati
✦ Un certificato contiene una chiave pubblica autenticata mediante la firma digitale di una Certification Authority (CA)
✦ Chi riceve il certificato può verificare direttamente l’autenticità della chiave pubblica usando la chiave pubblica della CA (che deve essere nota)
9
SSL/TLS✦ I protocolli di Internet (TCP/UDP/IP) non
offrivano inizialmente nessun supporto alla crittografia, che doveva essere realizzata a livello applicazione
✦ Nel 1995 Netscape propose un protocollo denominato Socket Security Layer (SSL) per rendere sicuro il web attraverso l’uso di crittografia a chiave pubblica
✦ Successivamente l’IETF ha recepito il protocollo come base per lo standard Transport Layer Security (TLS)
10
SSL/TLS
✦ Implementati a livello applicazione (nonostante il nome) mediante librerie (anche Open Source)
✦ Usati per incapsulare altri protocolli di livello applicazione (es. HTTP, SMTP etc.) in modo da renderli “sicuri”
11
Gestione delle chiavi e dei certificati
✦ Il Java Development Kit include un tool (da usare a linea di comando) per gestire chiavi e certificati: keytool
✦ Le chiavi pubbliche e private sono memorizzate in un keystore
✦ I certificati ritenuti “fidati” sono memorizzati in un truststore
✦ Il formato del keystore e del truststore è proprietario, ma keytool offre funzioni per import/export di chiavi e certificati nei formati dello standard X.509
12
Generazione delle chiavi
✦ Per generare una coppia di chiavi in un keystore il comando è:• keytool -genkey [opz...] -alias nome
-validity giorni -keystore keystore
✦ Il tool richiede alcune informazioni sull’identità della persona che genera le chiavi, che saranno memorizzate all’interno delle chiavi stesse
✦ Il keystore è protetto da una password
13
Generazione delle chiavi✦ Esempio
14
foggia% keytool -genkey -alias foggia -validity 365 -keystore keystore.jksImmettere la password del keystore: pippobaudoSpecificare nome e cognome [Unknown]: Pasquale FoggiaSpecificare il nome dell'unit? aziendale [Unknown]: diiieSpecificare il nome dell'azienda [Unknown]: unisaSpecificare la localit? [Unknown]: fiscianoSpecificare la provincia [Unknown]: saSpecificare il codice a due lettere del paese in cui si trova l'unit? [Unknown]: itIl dato CN=Pasquale Foggia, OU=diiie, O=unisa, L=fisciano, ST=sa, C=it ? corretto? [no]: s
Immettere la password della chiave per <foggia> (INVIO se corrisponde alla password del keystore): foggia%
Generazione delle chiavi✦ È possibile visualizzare il contenuto di un
keystore con il comando:• keytool -list -v -keystore keystore
15
foggia% keytool -list -v -keystore keystore.jks Immettere la password del keystore: pippobaudo
Tipo keystore: jksProvider keystore: SUN
Il keystore contiene 1 entry
Nome alias: foggiaData di creazione: 31-mar-2009Tipo entry: keyEntryLunghezza catena certificati: 1Certificato[1]:Proprietario: CN=Pasquale Foggia, OU=diiie, O=unisa, L=fisciano, ST=sa, C=itOrganismo di emissione: CN=Pasquale Foggia, OU=diiie, O=unisa, L=fisciano, ST=sa, C=itNumero di serie: 49d1e411Valido da Tue Mar 31 11:36:17 CEST 2009 a Wed Mar 31 11:36:17 CEST 2010Impronte digitali certificato: MD5: 58:A9:4F:D3:31:E9:C1:58:E3:75:5C:90:85:8D:81:13 SHA1: C1:20:ED:DC:43:14:00:F3:50:ED:07:15:D2:0A:93:B2:5C:38:21:B1
Generazione di certificati
✦ In genere il processo per generare un certificato richiede tre passi:• creazione di una Certificate Request a partire
dalla chiave pubblica nel keystore
• invio della Certificate Request alla CA, che produce il certificato
• importazione del certificato della CA nel truststore
16
Generazione di certificati✦ Non avendo a disposizione una CA,
genereremo un self-signed certificate• non c’è la garanzia sull’identità data dalla CA
• adeguato se i due end-point si fidano reciprocamente e possono scambiarsi i certificati in maniera sicura
✦ I passi diventano:• generazione del certificato dalla chiave pubblica
nel keystore
• importazione del certificato nel truststore
17
Generazione di certificati✦ Per generare il certificato, il comando è:
• keytool -export -alias nome -keystore keystore -rfc -file filecert
18
foggia% keytool -export -alias foggia -keystore keystore.jks -rfc -file foggia.cer Immettere la password del keystore: pippobaudoIl certificato ? memorizzato nel file <foggia.cer>foggia% foggia% cat foggia.cer -----BEGIN CERTIFICATE-----MIIDAjCCAsACBEnR5BEwCwYHKoZIzjgEAwUAMGcxCzAJBgNVBAYTAml0MQswCQYDVQQIEwJzYTERMA8GA1UEBxMIZmlzY2lhbm8xDjAMBgNVBAoTBXVuaXNhMQ4wDAYDVQQLEwVkaWlpZTEYMBYGA1UEAxMPUGFzcXVhbGUgRm9nZ2lhMB4XDTA5MDMzMTA5MzYxN1oXDTEwMDMzMTA5MzYxN1owZzELMAkGA1UEBhMCaXQxCzAJBgNVBAgTAnNhMREwDwYDVQQHEwhmaXNjaWFubzEOMAwGA1UEChMFdW5pc2ExDjAMBgNVBAsTBWRpaWllMRgwFgYDVQQDEw9QYXNxdWFsZSBGb2dnaWEwggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAACgYAwr9DQG3MVcFIPlzTr5yyAfn28J2PvzAQp9Eft84hLr7d9vGaSFY4vHrx0eCacuvouvBc6BzQo5H6CrbbeRaQQIGD5dTwORjI4qDWKZDNVL8EeEhTNLrsMb55jDNuw/epyHz6A/Fdz6/QgYp3bEYRTwwoIf4YJusTrzC500Ip2cjALBgcqhkjOOAQDBQADLwAwLAIULlNtybkWx9nm/yq0S3iW+AD4DvoCFHzBQCW9J/4qPGgfOpPaF43pt9In-----END CERTIFICATE-----
Generazione di certificati✦ Per importare il certificato, il comando è:
• keytool -import -alias nome -keystore truststore -file filecert
19
foggia% keytool -import -alias foggiacert -keystore truststore.jks -file foggia.cer Immettere la password del keystore: pippobaudoProprietario: CN=Pasquale Foggia, OU=diiie, O=unisa, L=fisciano, ST=sa, C=itOrganismo di emissione: CN=Pasquale Foggia, OU=diiie, O=unisa, L=fisciano, ST=sa, C=itNumero di serie: 49d1e411Valido da Tue Mar 31 11:36:17 CEST 2009 a Wed Mar 31 11:36:17 CEST 2010Impronte digitali certificato: MD5: 58:A9:4F:D3:31:E9:C1:58:E3:75:5C:90:85:8D:81:13 SHA1: C1:20:ED:DC:43:14:00:F3:50:ED:07:15:D2:0A:93:B2:5C:38:21:B1Considerare attendibile questo certificato? [no]: sIl certificato ? stato aggiunto al keystorefoggia%foggia% keytool -list -keystore truststore.jks Immettere la password del keystore: pippobaudo
Tipo keystore: jksProvider keystore: SUN
Il keystore contiene 1 entry
foggiacert, 31-mar-2009, trustedCertEntry,Impronta digitale certificato (MD5): 58:A9:4F:D3:31:E9:C1:58:E3:75:5C:90:85:8D:81:13
Comunicazione con Socket SSL/TLS
✦ In Java l’uso di SSL/TLS si basa sulle classi SSLSocket e SSLServerSocket, che estendono rispettivamente Socket e ServerSocket
✦ Una volta effettuata la creazione dei socket, non c’è differenza per l’applicazione rispetto all’uso di socket non crittografati
20
Creazione di socket SSL
✦ Le classi e le interfacce necessarie sono nei package:• javax.net.*
• javax.net.ssl.*
✦ Il primo passo è la creazione di una SocketFactory, che è un oggetto che astrae l’operazione di creazione di un socket
21
Creazione di un socket SSL✦ Per creare una SocketFactory in grado di
creare Socket SSL occorre usare il metodo static getDefault() della classe SSLSocketFactory
22
SocketFactory factory=SSLSocketFactory.getDefault();
Creazione di un socket SSL✦ Una volta ottenuta una factory, si può
usare il metodo createSocket() per creare il socket vero e proprio:
✦ Una volta creato, il socket si usa come un normale client socket
23
Socket sock=factory.createSocket(host, port);
Keystore e truststore
✦ Per rendere possibile la creazione del socket SSL, il programma deve conoscere il keystore e il truststore e le relative password
✦ È possibile fornire tali informazioni usando opportune proprietà di sistema
24
Keystore e truststore
✦ Le proprietà di sistema possono essere impostate con il metodo System.setProperty():
25
System.setProperty("javax.net.ssl.keyStore", "clientkeystore.jks");System.setProperty("javax.net.ssl.keyStorePassword", "pippobaudo");System.setProperty("javax.net.ssl.trustStore", "clienttruststore.jks");System.setProperty("javax.net.ssl.trustStorePassword", "pippobaudo");
Creazione di Server Socket
✦ La creazione di server socket SSL è analoga alla creazione di socket
✦ Occorre usare le classi:• ServerSocketFactory
• SSLServerSocketFactory
• SSLServerSocket
26
Creazione di Server Socket✦ Esempio:
27
ServerSocketFactory factory=SSLServerSocketFactory.getDefault();ServerSocket sock=factory.createServerSocket(port);
✦ Una volta creato, il server socket si usa esattamente come un ServerSocket non crittografato
✦ Il keystore e il truststore devono essere specificati con le stesse proprietà di sistema
Creazione di Server Socket✦ Per default i socket creati dalla factory
effettuano l’autenticazione del solo server✦ Se si desidera l’autenticazione anche del
client, occorre convertire il socket in un SSLServerSocket e richiamare il metodo setNeedClientAuth()
28
ServerSocketFactory factory=SSLServerSocketFactory.getDefault();SSLServerSocket sock=(SSLServerSocket)
factory.createServerSocket(port);sock.setNeedClientAuth(true);
Un client completo
29
import java.io.*;import java.net.*;import javax.net.*;import javax.net.ssl.*;
public class SSLEchoClient { public static final int PORT=7777; public static Socket createSocket(String host, int port) throws IOException { SocketFactory factory=SSLSocketFactory.getDefault(); Socket sock=factory.createSocket(host, port); return sock; }
// continua ...
Un client completo
30
public static void main(String args[]) throws IOException { System.setProperty("javax.net.ssl.keyStore", "clientkeystore.jks"); System.setProperty("javax.net.ssl.keyStorePassword", "pippobaudo"); System.setProperty("javax.net.ssl.trustStore", "clienttruststore.jks"); System.setProperty("javax.net.ssl.trustStorePassword", "pippobaudo");
Socket sock=createSocket(args[0], PORT); OutputStream os=sock.getOutputStream(); Writer wr=new OutputStreamWriter(os, "UTF-8"); PrintWriter prw=new PrintWriter(wr); prw.println("Hello, world"); prw.flush(); InputStream is=sock.getInputStream(); Reader rd=new InputStreamReader(is, "UTF-8"); BufferedReader brd=new BufferedReader(rd); String answer=brd.readLine(); System.out.println(answer); sock.close(); }}
Un server completo
31
import java.io.*;import java.net.*;import javax.net.*;import javax.net.ssl.*;
public class SSLEchoServer implements Runnable { public static final int PORT=7777; private Socket sock; public SSLEchoServer(Socket s) { sock=s; } public static ServerSocket createServerSocket(int port) throws IOException { ServerSocketFactory factory=SSLServerSocketFactory.getDefault(); SSLServerSocket sock=(SSLServerSocket) factory.createServerSocket(port); sock.setNeedClientAuth(true); return sock; } // continua ...
Un server completo
32
public static void main(String args[]) throws IOException { System.setProperty("javax.net.ssl.keyStore", "servkeystore.jks"); System.setProperty("javax.net.ssl.keyStorePassword", "pippobaudo"); System.setProperty("javax.net.ssl.trustStore", "servtruststore.jks"); System.setProperty("javax.net.ssl.trustStorePassword", "pippobaudo"); ServerSocket serv=createServerSocket(PORT); while (true) { Socket sock=serv.accept(); SSLEchoServer server=new SSLEchoServer(sock); Thread t=new Thread(server); t.start(); } } // continua...
Un server completo
33
public void run() { try { BufferedReader brd=new BufferedReader( new InputStreamReader( sock.getInputStream(), "UTF-8")); String s=brd.readLine(); PrintWriter prw=new PrintWriter( new OutputStreamWriter( sock.getOutputStream(), "UTF-8")); prw.print(s); prw.println(s); prw.flush(); } catch (IOException exc) { System.out.println("Eccezione I/O:" + exc); exc.printStackTrace(); } finally { try { sock.close(); } catch (IOException exc2) { } } }}