Un keystore es un archivo especial utilizado para almacenar claves criptográficas, como claves privadas y públicas, junto con certificados digitales. Este almacén se protege mediante una contraseña y garantiza que las claves almacenadas estén seguras y solo sean accesibles a quienes tienen la autorización correcta.
El keystore se utiliza comúnmente en aplicaciones Java y viene en varios formatos, como:
Antes de almacenar una clave RSA, primero necesitamos crear un keystore. Podemos hacerlo usando la herramienta keytool
, que viene integrada con cualquier JDK.
keytool -genkeypair -alias mykey -keyalg RSA -keysize 2048 -validity 3650 -keystore mykeystore.p12 -storetype PKCS12 -storepass mypassword
Explicación de los parámetros:
-alias
: Es el alias bajo el cual se almacenará la clave dentro del keystore.
-keyalg
: Especifica el algoritmo de clave. En este caso, estamos usando RSA.
-keysize
: Define el tamaño de la clave. 2048 bits es el estándar recomendado para claves RSA.
-validity
: La validez de la clave en días. Aquí está configurado para 10 años (3650 días).
-keystore
: El nombre del archivo del keystore.
-storetype
: El tipo de keystore, en este caso PKCS12.
-storepass
: La contraseña del keystore.
Una vez creado, el keystore contendrá una clave privada y un certificado autofirmado.
Ahora que tenemos el keystore, debemos configurarlo en nuestra aplicación Spring Boot. La forma más directa es hacerlo en el archivo application.properties
o application.yml
.
application.properties
server.ssl.key-store=classpath:mykeystore.p12
server.ssl.key-store-password=mypassword
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=mykey
application.yml
server:
ssl:
key-store: classpath:mykeystore.p12
key-store-password: mypassword
key-store-type: PKCS12
key-alias: mykey
En esta configuración:
key-store
: Especifica la ruta del keystore. Si está en el classpath, lo colocamos en src/main/resources
.
key-store-password
: La contraseña que utilizamos al crear el keystore.
key-store-type
: El tipo de keystore, en este caso PKCS12.
key-alias
: El alias de la clave RSA que se utilizará.
Para acceder a la clave almacenada en el keystore y utilizarla en tu aplicación, por ejemplo, para firmar JWTs o realizar operaciones de cifrado, podemos usar las utilidades de Java para trabajar con keystores.
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
public class KeystoreUtil {
public PrivateKey loadPrivateKey() throws Exception {
// Cargar el keystore desde resources
KeyStore keystore = KeyStore.getInstance("PKCS12");
try (InputStream is = getClass().getClassLoader().getResourceAsStream("mykeystore.p12")) {
keystore.load(is, "mypassword".toCharArray());
}
// Obtener la clave privada con su alias y la contraseña
PrivateKey privateKey = (PrivateKey) keystore.getKey("mykey", "mypassword".toCharArray());
// Devolver la clave privada
return privateKey;
}
public Certificate loadCertificate() throws Exception {
// Cargar el keystore desde resources
KeyStore keystore = KeyStore.getInstance("PKCS12");
try (InputStream is = getClass().getClassLoader().getResourceAsStream("mykeystore.p12")) {
keystore.load(is, "mypassword".toCharArray());
}
// Obtener el certificado asociado
Certificate certificate = keystore.getCertificate("mykey");
// Devolver el certificado
return certificate;
}
}
En este código:
Uno de los casos más comunes para utilizar una clave RSA es firmar JSON Web Tokens (JWT). Aquí te mostramos un ejemplo usando la biblioteca jjwt para firmar un JWT con la clave RSA.
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
</dependency>
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.security.PrivateKey;
import java.util.Date;
public class JwtUtil {
private final PrivateKey privateKey;
public JwtUtil(PrivateKey privateKey) {
this.privateKey = privateKey;
}
public String generateToken(String subject) {
return Jwts.builder()
.setSubject(subject)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1 hora de expiración
.signWith(privateKey, SignatureAlgorithm.RS256)
.compact();
}
}
Cuando trabajamos con claves criptográficas en un entorno de producción, debemos tener en cuenta varias mejores prácticas:
El uso de un keystore para almacenar claves RSA en producción con Spring Boot es una forma segura y eficiente de gestionar claves criptográficas. Siguiendo los pasos descritos en este artículo, puedes proteger tus claves y utilizar el keystore para firmar JWTs, cifrar datos o cualquier otra operación criptográfica en tu aplicación. Además, asegurarte de aplicar las mejores prácticas de seguridad en la gestión del keystore y las claves criptográficas es fundamental para mantener la integridad y confidencialidad de tu sistema en un entorno de producción.
Jorge García
Fullstack developer