Volver a la página principal
lunes 23 septiembre 2024
76

Cómo utilizar el keystore para almacenar una clave RSA en producción con Spring Boot

¿Qué es un keystore?

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:

  • JKS (Java KeyStore): El formato más utilizado en el ecosistema Java.
  • PKCS12: Un estándar multiplataforma que se está convirtiendo en la opción predeterminada en muchas aplicaciones debido a su compatibilidad con otros sistemas.

Configurando Spring Boot para utilizar un keystore

1. Crear un Keystore

Antes de almacenar una clave RSA, primero necesitamos crear un keystore. Podemos hacerlo usando la herramienta keytool, que viene integrada con cualquier JDK.

Comando para crear un keystore con un par de claves RSA

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.

2. Configurar el keystore en Spring Boot

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.

Configuración en 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

Configuración en 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á.

3. Cargar la clave RSA desde el keystore

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.

Cargar la clave privada

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:

  • Cargamos el keystore desde el classpath.
  • Utilizamos la contraseña para desbloquear el keystore.
  • Obtenemos la clave privada usando el alias y la contraseña que definimos al crear el keystore.

4. Uso de la clave RSA para firmar JWTs

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.

Dependencia de Maven

<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>

Código para generar un JWT firmado

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();
    }
}

5. Prácticas recomendadas para producción

Cuando trabajamos con claves criptográficas en un entorno de producción, debemos tener en cuenta varias mejores prácticas:

  • Protección del keystore: Asegúrate de que el archivo del keystore no esté expuesto públicamente. Solo debería estar accesible para los procesos autorizados.
  • Rotación de claves: Implementa un sistema para rotar las claves regularmente para minimizar el riesgo en caso de un ataque.
  • Almacenamiento seguro de contraseñas: No incluyas contraseñas sensibles en archivos de configuración. Utiliza servicios de gestión de secretos como HashiCorp Vault o AWS Secrets Manager para proteger estas credenciales.
  • Monitoreo de acceso: Registra y monitorea el acceso al keystore para detectar posibles actividades sospechosas.

Conclusión

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.

Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer