Diferencias entre Java Keystore y Truststore

Diferencias entre un Java Keystore y un Java Truststore

En este tutorial rápido, proporcionaremos una visión general de las diferencias entre un Java keystore y un Java truststore.

Conceptos

En la mayoría de los casos, utilizamos un keystore y un truststore cuando nuestra aplicación necesita comunicarse a través de SSL/TLS. Normalmente, estos son archivos protegidos por contraseña que se encuentran en el mismo sistema de archivos que nuestra aplicación en ejecución. El formato predeterminado utilizado para estos archivos fue JKS hasta Java 8.
Desde Java 9, el formato de keystore predeterminado es PKCS12. La diferencia más importante entre JKS y PKCS12 es que JKS es un formato específico de Java, mientras que PKCS12 es una forma estandarizada y neutral a nivel de lenguaje de almacenar claves privadas y certificados cifrados.

Java KeyStore

Un Java keystore almacena entradas de claves privadas, certificados con claves públicas, o simplemente claves secretas que podemos usar para diversos propósitos criptográficos. Almacena cada entrada por un alias para facilitar su búsqueda.
Generalmente, los keystores mantienen las claves que nuestra aplicación posee, que podemos usar para probar la integridad de un mensaje y la autenticidad del remitente, por ejemplo, al firmar cargas útiles.
Normalmente, utilizaremos un keystore cuando somos un servidor y queremos usar HTTPS. Durante un apretón de manos SSL, el servidor busca la clave privada en el keystore y presenta su clave pública y certificado correspondiente al cliente.
De manera similar, si el cliente también necesita autenticarse, en una situación llamada autenticación mutua, el cliente también tiene un keystore y presenta su clave pública y certificado.
No hay un keystore predeterminado, así que si queremos utilizar un canal cifrado, debemos establecer javax.net.ssl.keyStore y javax.net.ssl.keyStorePassword. Si nuestro formato de keystore es diferente al predeterminado, podemos usar javax.net.ssl.keyStoreType para personalizarlo.
Por supuesto, podemos usar estas claves para satisfacer otras necesidades también. Las claves privadas pueden firmar o descifrar datos, y las claves públicas pueden verificar o cifrar datos. Las claves secretas también pueden realizar estas funciones. Un keystore es un lugar donde podemos mantener estas claves.

import java.security.KeyStore;

// Crear un nuevo keystore
public class KeyStoreExample {
    public static void main(String[] args) throws Exception {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // Cargar el keystore
        keyStore.load(null, null);
        // Agregar una clave privada y un certificado
        // ... Código para agregar claves
    }
}
    

Java TrustStore

Un truststore es lo opuesto. Mientras que un keystore típicamente contiene certificados que nos identifican, un truststore contiene certificados que identifican a otros.
En Java, lo usamos para confiar en un tercero con el que estamos a punto de comunicarnos.
Tomemos nuestro ejemplo anterior. Si un cliente se comunica con un servidor basado en Java a través de HTTPS, el servidor buscará la clave asociada en su keystore y presentará la clave pública y el certificado al cliente.
Nosotros, como clientes, luego buscamos el certificado asociado en nuestro truststore. Si el certificado o las Autoridades de Certificación presentadas por el servidor externo no están en nuestro truststore, obtendremos una SSLHandshakeException, y la conexión no se establecerá exitosamente.
Java tiene un truststore incorporado llamado cacerts. Para versiones de Java anteriores a la 9, se encuentra en el directorio $JAVA_HOME/jre/lib/security, y para versiones de Java posteriores a la 8, está en $JAVA_HOME/lib/security.
Contiene autoridades de certificación predeterminadas:

$ keytool -list -keystore cacerts
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 92 entries

verisignclass2g2ca [jdk], 2018-06-13, trustedCertEntry,
Certificate fingerprint (SHA1): B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9D
    
Podemos ver aquí que el truststore contiene 92 entradas de certificados confiables y una de las entradas es la verisignclass2g2ca. Esto significa que la JVM confiará automáticamente en los certificados firmados por verisignclass2g2ca.
Podemos sobrescribir la ubicación del truststore predeterminado a través de la propiedad javax.net.ssl.trustStore. De manera similar, podemos establecer javax.net.ssl.trustStorePassword y javax.net.ssl.trustStoreType para especificar la contraseña y el tipo del truststore.

Conclusión

En este artículo, discutimos las principales diferencias entre el Java keystore y el Java truststore, junto con sus propósitos.
Aprendimos que los keystores almacenan las claves necesarias para que nuestra aplicación se identifique y autentique, mientras que los truststores verifican la identidad de terceros en las comunicaciones. Además, abordamos cómo los valores predeterminados se pueden anular mediante propiedades del sistema.
Para profundizar más en la comunicación cifrada en Java, podemos consultar la siguiente guía de SSL o el Guía de Referencia JSSE.
Mantente al tanto de las mejores prácticas y asegúrate de entender bien estos conceptos para mejorar la seguridad y la robustez de tus aplicaciones en Java. ¡Feliz codificación!