Post on 09-Jul-2022
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL1
Especialista en Aplicaciones y Servicios Web con Java Enterprise
Programación de Seguridad en Java
Sesión 5Protocolo SSL
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL2
SSL básico. Funcionamiento y HTTPSInstalando y configurando JSSECliente y servidor HTTPSProtegiendo “keystore” y passwordAutentificación del cliente
Índice
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL3
SSL básico. Funcionamiento y HTTPSInstalando y configurando JSSECliente y servidor HTTPSProtegiendo “keystore” y passwordAutentificación del cliente
SSL básico. Funcionamiento y HTTPS
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL4
Motivación: SSL: Protocolo de encriptación de comunicación cliente-servidor: POP, IMAP, telnet, FTP,…Pero sobre todo es el soporte para dotar de seguridad a HTTP: protocolo HTTPS.Implementación: extensión de los “sockets” que mantiene un canal de comunicación después de un “handshake”.Durante el “handshake” cliente y servidor construyen una “session-key”.
SSL básico. Funcionamiento y HTTPS
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL5
“Handshake” (esquema):
SSL básico. Funcionamiento y HTTPS
client_hello
server_hellocertificado_servidor(pedir_certificado)server_hello_done
(certificado_cliente)client_key_exchange(certificate_verify)change_cipher_spec
finished
change_cipher_specfinished
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL6
Handshake: 1. Cliente envía un client_hello que contiene:
Versión de SSL soportada por el cliente32 bytes de datos aleatoriosIdentificador de sesiónLista de “ciphers” soportadosLista de métodos de compresión soportados
2. Servidor responde un server_hello que contiene:Versión de SSL que selecciona de la lista del cliente32 bytes de datos aleatorios Identificador de sesiónCifradores seleccionados de la lista del cliente (RSA, RCA)Método de compresión (usualmente ninguno).
SSL básico. Funcionamiento y HTTPS
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL7
Handshake: 2. (sigue) Servidor envía un certificado X.509 firmado por
una CA y que contiene la clave pública del servidor. Opcionalmente puede pedir certificado al cliente. Después envía un server_hello_done y espera.
3. Cliente verifica el mensaje del servidor y si se le requiere un certificado se lo envía. Seguidamente envía un client_key_exchange con 48 bytes (sacados de los 32 del cliente y 32 del servidor) que se usan para construir la “session-key” que es encriptada por la clave pública del certificado del servidor.
SSL básico. Funcionamiento y HTTPS
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL8
Handshake: 3. (sigue) A continuación, el cliente envía un
cerificate_verify si se le pidió un certificado. En cualquier caso, después construye una clave simétrica con RC4 y una clave para el MAC que se usará para comprobar la integridad de los datos. Después envía un change_cipher_spec para indicar los parámetros del cifrado, y finalmente un finished.
4. Servidor responde con su change_cipher_specpara indicar los parámetros y con finished.
SSL básico. Funcionamiento y HTTPS
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL9
SSL básico. Funcionamiento y HTTPSInstalando y configurando JSSECliente y servidor HTTPSProtegiendo “keystore” y passwordAutentificación del cliente
Instalando y configurando JSSE
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL10
JSEE: Implementa SSL de forma transparente. Básicamente permite definir y manejar “sockets” seguros. Instalación y configuración:
Descargarlo de java.sun.com/products/jseeColocar jcert.jar, jnet.jar, jsse.jar en $JAVA_HOME/jre/lib/extModificar el fichero $JAVA_HOME/jre/lib/security/java.security para que contenga la línea que especifica un nuevo proveedor de seguridad
Instalando y configurando JSSE
Security.provider.x=com.sun.net.ssl.internal.ssl.Provider
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL11
SSL básico. Funcionamiento y HTTPSInstalando y configurando JSSECliente y servidor HTTPSProtegiendo “keystore” y passwordAutentificación del cliente
Cliente y servidor HTTPS
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL12
Cliente: (ClienteHTTPS.java) Hay que indicarle al manejador de URLs donde están las clases SSL:
java -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocolClienteHTTPS https://www.thawte.com
Alternativamente se puede hacer desde código a través de setProperty():
Cliente y servidor HTTPS
System.setProperty(
"java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL13
Servidor: (ServidorHTTPS.java) Crear un “socket” SSL: Server Socket• Usar javax.net.ssl.SSLServerSocketFactory para
obtener una SSLServerSocketFactory.• Llamar a createServerSocket()
A partir de aquí el servidor actúa de forma transparente: accept(), InputStream (cliente), OutputStream(pantalla). Después construye una página HTML y finalmente cierra “streams” y el “socket”.
Cliente y servidor HTTPS
SSLServerSocketFactory ssf = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();ServerSocket ss = ssf.createServerSocket(8080);
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL14
Servidor: (ServidorHTTPS.java) Sin embargo, si lanzamos java ServidorHTTPS se lanzaráuna excepción puesto que no se creado un certificado y una clave privada para el servidor SSLPara crearla con “keytool”: keytool –genkey –v –keyalg RSA –keystore .kestoreSiendo el CN=localhost. Así, para lanzar el servidor indicaremos a la MV el almacén que contiene el certificado y el password para acceder a él:
java -Djavax.net.ssl.keyStore=.keystore
-Djavax.net.ssl.keyStorePassword=scosco ServidorHTTPS
Cliente y servidor HTTPS
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL15
Servidor: (ServidorHTTPS.java) Tras esperar unos segundos desde el navegador atacaremos el puerto 8080: https://localhost:8080 donde está escuchando el servidor.Sin embargo, dado que el certificado es auto-firmado nuestro navegador no lo reconocerá y nos pedirá si queremos aceptarlo. Si decimos que sí se muestra una página HTML con “Hola!”. Para salvar las advertencias hay que usar un certificado de una CA reconocida por nuestra MV, como Verisign.
Cliente y servidor HTTPS
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL16
Cliente:(“trustore”) Para que el cliente confíe en el certificado auto-firmado del servidor podemos hacer que su trustStore (almacén de certificados en quien confía) sea el mismo almacén que el que contiene dicho certificado:
java –Djavax.net.ssl.trustStore=.keystore ClienteHTTPS https://localhost:8080/
El trustStore por defecto es el fichero$JRE_HOME/lib/security/cacerts
No obstante, podemos importar certificados en el cacerts de la siguiente forma:
keytool –impor –alias certificado –file certificado.cer –keystore cacerts
Cliente y servidor HTTPS
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL17
SSL básico. Funcionamiento y HTTPSInstalando y configurando JSSECliente y servidor HTTPSProtegiendo “keystore” y passwordAutentificación del cliente
Protegiendo “keystore” y password
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL18
Motivación: Pasar el almacén y su password por línea de comandosno es muy seguro (alguien puede verlo con un “ps”). Es más conveniente definir el password y cargar el almacén desde código. Utilizaremos las clases de com.sun.net.ssl: • TrustManagerFactory (en el cliente)• KeyManagerFactory (en el servidor)• SSLContext en ambos
Resultado: • ClienteSSLSocketsSun.java• ServidorSSLSocketsSun.java
Protegiendo “keystore” y password
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL19
Cliente: (ClienteSSLSocketsSun.java) Suponemos el password “conocido” para cargar el “keystore” que nos interesa:
Inicializamos una TrustManagerFactory
Protegiendo “keystore” y password
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(keystore);
char[] password = "scosco".toCharArray();KeyStore keystore = KeyStore.getInstance("JKS");keystore.load(new FileInputStream(".keystore"), password);
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL20
Cliente: (ClienteSSLSocketsSun.java) Ya podemos crear un SSLContext:
Este contexto permite definir una SSLSocketFactorypara que podamos implementar el cliente con “sockets”(sin basarnos en peticiones HTTPS)
Protegiendo “keystore” y password
SSLContext contexto = SSLContext.getInstance("TLS");TrustManager[] trustManagers = tmf.getTrustManagers();contexto.init(null, trustManagers, null);
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL21
Servidor: (ServidorSSLSocketsSun.java) Una vez conocido el password y cargado el “keystore”inicializará con éste una KeyManagerFactory y con ella un SSLContext:
Protegiendo “keystore” y password
KeyManagerFactorykmf = KeyManagerFactory.getInstance("SunX509");kmf.init(keystore, password);SSLContext contexto = SSLContext.getInstance("TLS");KeyManager[] keyManagers = kmf.getKeyManagers();contexto.init(keyManagers, null, null);SSLServerSocketFactory ssf = contexto.getServerSocketFactory();ServerSocket ss = ssf.createServerSocket(PORT);
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL22
SSL básico. Funcionamiento y HTTPSInstalando y configurando JSSECliente y servidor HTTPSProtegiendo “keystore” y passwordAutentificación del cliente
Autentificación del cliente
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL23
Motivación: Por defecto solo el servidor está obligado a autentificarse (el cliente se considera “anonimo”). Si queremos forzar la autentificación del cliente, éste deberá presentar un certificado. ServidorHTTPSAutorizando.java
Autentificación del cliente
// Utilizar una SocketFactory para crear sockets SSL:SSLServerSocketFactory ssf =(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();SSLServerSocket ss =
(SSLServerSocket)ssf.createServerSocket(8080);// Requerir autentificación del clientess.setNeedClientAuth(true);
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL24
Cliente: (ClienteHTTPS.java) Pero antes, la autorización mútua fuerza a que el cliente incorpore en su trustStore un certificado del servidor (y viceversa:1. Keystore del cliente:keytool –genkey –v –keyalg RSA -keystore ks_cliente
(con “CN=sco” y clave “scosco”)
2. Keystore del servidor: keytool –genkey –v –keyalg RSA -keystore ks_servidor
(con “CN=localhost” y clave “dcciadccia”)
3. Certificado del servidorkeytool –export –v –file servidor.cer –keystore ks_servidor
Autentificación del cliente
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL25
Lanzamos servidorjava -Djavax.net.ssl.keyStore=ks_servidor
-Djavax.net.ssl.keyStorePassword=dcciadccia-Djavax.net.ssl.trustStore=ts_servidor
ServidorHTTPSAutorizando
Lanzamos clientejava -Djavax.net.ssl.keyStore=ks_cliente
-Djavax.net.ssl.keyStorePassword=scosco-Djavax.net.ssl.trustStore=ts_servidorClienteHTTPS https://localhost:8080
…y el cliente ya puede acceder a la página web.
Autentificación del cliente
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL26
ServidorHTTPSAutorizando2.javaAutentificar al cliente no en base al certificado completoen base a ciertos datos como el CN. Despues de accept()
Autentificación del cliente
boolean permitido = false;// Obtener la sesionSSLSession sesion = ((SSLSocket) s).getSession();// Comprobar la autentificación del cliente con el AutentificadorCNAutentificadorCN autentificador = newAutentificadorCN(sesion);try {autentificador.comprobarPermiso();permitido = true;
} catch (ExcepcionAutentificacion ea) {permitido = false;System.out.println("Acceso denegado." + ea);
}
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL27
AutentificadorCN.java
Autentificación del cliente
// 1. Obtener la secuencia de certificados.X509Certificate[] certChain = null;try {
certChain = mSession.getPeerCertificateChain();} catch (SSLPeerUnverifiedException spue) {throw new ExcepcionAutentificacion("Error cadena");}// 2. Obtener el certificado del clienteX509Certificate clientCert = certChain[0];// 3. Obtener el principal correspondiente al clientejava.security.Principal client = clientCert.getSubjectDN();// 4. Obtener el nombre del clienteString name = client.getName();// 5. Comprobar que CN=scoif (name.indexOf("CN=sco,")!=0) {throw new ExcepcionAutentificacion("Cliente no es sco");
}
Programación de Seguridad en Java © 2003-2004 Depto. Ciencia Computación e IA SSL28
Ejercicio7.java…Usando JCEKS. Formato alternativo al JKS que utiliza PBE para encriptar las claves. • Desde keytool hay que usar la opción –storetype JCEKS• Dede línea de comandos –D.javax.net.ssl.keyStoreType=JCEKS
Se pide: modificar cliente y servidor basados en las clases de com.sun.net.ssl para que trabajen con almacenes de este tipo. ClienteSSLSocketsSun.java, ServidorSSLSocketsSun.java
Ejercicios…