User Tools

Site Tools


probar_conexiones_https_desde_java_jvm

Comprobar problemas de certificados SSL en aplicaciones Java (JVM)

Las aplicaciones Java no utilizan la lista de certificados de confianza (trustStore) disponible en el sistema operativo, si no que tienen la suya propia en formato Java KeyStore (JKS). A esa lista se refieren los nombres de “almacén de claves”, “repositorios de certificados”, “listado de certificados confiables”, “Java trustStore”, “keystore”, etc. Realmente un JKS puede tener cualquier tipo de llaves, no necesariamente tiene que tener la finalidad de albergar certificados de CAs confiables. Un Java KeyStore puede contener también llaves privadas para realizar otro tipo de conexiones SSL.

Dependiendo de la aplicación Java utilizada, esta usará el listado / repositorio de certificados de confianza de la propia máquina virtual JVM o bien usará un keystore propio, también en formato JKS. Naturalmente es posible arrancar la JVM especificando un trustStore concreto y no el predeterminado de la máquina virtual Java instalada, algo útil a la hora de hacer pruebas.

El Java Development Kit (JDK) mantiene dicho almacén de claves de entidades certificadoras confiables en el archivo “<java_home>/jre/lib/security/cacerts”. Para trabajar sobre dicho keystore, JDK proporcionan una herramienta llamada “keytool”. Pese a que dicha herramienta no tiene funcionalidad para extraer la llave privada del almacén de claves, es posible utilizar herramientas de terceros como jksExportKey, CERTivity, Portecle y KeyStore Explorer para tal fin.

Muchas aplicaciones Java no permiten ignorar certificados autofirmados o con firmas de CAs no confiables. Si la aplicación Java o la máquina virtual sobre la que corre es antigua, es posible que muchos de los nuevos certificados creados por las CAs no sean reconocidos. Esto ocasiona infinidad de problemas en aplicaciones Java al configurar conexiones cifradas SMTP/POP/IMAP/HTTPS/…

Ejemplo de un mensaje de error en Jira al usar un servidor POP / IMAP con certificado de una CA interna (no confiable).

Unfortunately no connection was possible. Review the errors below and rectify:
SunCertPathBuilderException: unable to find valid certification path to requested target

En algunos casos las aplicaciones dan pistas sobre el problema en forma de avisos / errores. De no ser así, se debe mirar en los logs. Para comprobar cómodamente si una aplicación o máquina virtual Java desconfía de algún tipo de conexiones SSL, se recomienda usar este sencillo código Java.

SSLPoke: https://gist.github.com/4ndrej/4547029

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
 
/** Establish a SSL connection to a host and port, writes a byte and
 * prints the response. See
 * http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services
 */
public class SSLPoke {
    public static void main(String[] args) {
        if (args.length != 2) {
            System.out.println("Usage: "+SSLPoke.class.getName()+" <host> <port>");
            System.exit(1);
        }
        try {
            SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
            SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1]));
 
            InputStream in = sslsocket.getInputStream();
            OutputStream out = sslsocket.getOutputStream();
 
            // Write a test byte to get a reaction :)
            out.write(1);
 
            while (in.available() > 0) {
                System.out.print(in.read());
            }
            System.out.println("Successfully connected");
 
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

Compilar y ejecutar SSLPoke contra una IP y puerto.

javac SSLPoke.java 
# Utilizando el keystore predeterminado.
java SSLPoke XXXXX 443
 
# Utilizando un keystore no predeterminado al ejecutar aplicaciones Java, en este caso SSLPoke.
java -Djavax.net.ssl.trustStore=./LocalTrustStore -jar SSLPoke.jar XXXXX 443
 
# Salida cuando Java confía en el certificado.
Successfully connected
 
# Salida cuando Java NO confía en el certificado: Se debe agregar el nuevo certificado o bien su CA raiz al keystore.
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Obtener un certificado que actualmente esté en linea para agregarlo posteriormente a un keystore.

# POP SSL (Puerto 995)
openssl s_client -connect XXXX:995 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/public.crt
 
# HTTPS (Puerto 443)
openssl s_client -connect XXXX:443 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/public.crt

Contraseña predeterminada de los keystorage: changeit

Listar los alias de los certificados contenidos en un keystore.

keytool -list -v -keystore /opt/atlassian/jira/jre/lib/security/cacerts | grep -i aliasname

Agregar un certificado a una Java keystore (JKS): Se le debe asignar un alias

keytool -import -alias Nueva_CA -keystore /usr/java/jdk1.8.0_65/jre/lib/security/cacerts -file /tmp/CA_nueva.cer
probar_conexiones_https_desde_java_jvm.txt · Last modified: 2020/12/25 22:57 by 127.0.0.1