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
}
}
Podemos también interactuar con el keystore programáticamente.
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!