Generando llaves públicas y privadas en Java

La creación de llaves públicas y privadas ayuda principalmente a la criptografía para poder así establecer comunicaciones seguras entre diferentes dispositivos, cifrando los mensajes con una de las llaves y descifrando con la otra, la llave pública es repartida a los diferentes dispositivos a los que te quieras comunicar y la llave privada se asegura con el alma para que nadie más la tenga, solo tú. Este tipo de cifrado puedes usarlo de dos maneras principalmente:

  • La primera forma es cifrando los mensajes con la llave pública, donde solo la llave privada puede descifrar el mensaje.
  • La segunda forma es cifrando los mensajes con la llave privada y descifrando con la llave pública. Haciendo de que se pueda saber de donde viene el mensaje 😉

Java nos brinda toda una librería para los aspectos de seguridad, la cual se encuentra en el paquete java.security, donde una parte se puede utilizar para la generación de este par de llaves.

¿Cómo generar un par de llaves pública y privada?

Lo primero que se tiene que hacer es obtener la instancia de la clase KeyPairGenerator a través del método getInstance() de esa misma clase, enviando por parámetro el algoritmo que se va a utilizar, en este caso voy a utilizar RSA, luego de ello se tiene que inicializar utilizando el método initialize() estableciendo el número de bits a utilizar. Y luego, por último solo se generan el par de llaves con el método generateKeyPair() como lo muestra el siguiente fragmento de código.


try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

Al final podemos obtener la llave pública y privada con los respectivos métodos de la clase KeyPair.getPublic() y KeyPair.getPrivate().

De esta forma hemos generado un par de llaves pública y privada para usar en algún cifrado de información.

Ahora seguramente te interese guardar estas llaves, bueno, simple, tienes dos maneras.

¿Cómo guardar las llaves en texto plano?

Por lo general el par de llaves generadas suelen guardarse en texto plano para poder ser utilizadas en la web para realizar pruebas, para esto, debes hacer lo siguiente:


Base64.Encoder encoder = Base64.getEncoder();
try (FileWriter out = new FileWriter(fileName)) {
out.write("—-BEGIN RSA PRIVATE KEY—-");
out.write("\n");
out.write(encoder.encodeToString(prviateKey.getEncoded()));
out.write("\n");
out.write("—-END RSA PRIVATE KEY—-");
out.write("\n");
} catch (IOException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
}


Base64.Encoder encoder = Base64.getEncoder();
try (FileWriter out = new FileWriter(fileName)) {
out.write("—-BEGIN RSA PUBLIC KEY—-");
out.write("\n");
out.write(encoder.encodeToString(publicKey.getEncoded()));
out.write("\n");
out.write("—-END RSA PUBLIC KEY—-");
out.write("\n");
} catch (IOException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
}

Como nos damos cuenta, para guardar cada una de las llaves necesitamos de la case Base64 para codificar nuestra llave, y dependiendo de si la clave es públicaprivada se colocará un encabezado o un pie totalmente distinto.

Al final simplemente escribimos el archivo que creamos con la clase FileWriter.

¿Cómo guardar las llaves en un archivo binario?

En este caso es mucho más sencillo ya que no se necesita de codificar nuestra llave, simplemente es tomar los bytes de nuestra llave y guardarla, como lo muestra el siguiente código:


try (FileOutputStream out = new FileOutputStream(fileName)) {
out.write(key.getEncoded());
} catch (IOException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
}

Como pueden ver, independientemente de si la llave es pública o privada, obtenemos de esta un arreglo de bytes y eso lo escribimos en el archivo que acabamos de crear con la clase FileOutputStream.

Para finalizar…

Para finalizar podemos imprimir el formato en que fueron guardados las llaves para saber como podemos leer luego estas llaves, esto lo hacemos con el siguiente código:


LOG.info(String.format("Public key format: %s", publicKey.getFormat()));
LOG.info(String.format("Private key format: %s", privateKey.getFormat()));

Dándonos como respuesta los siguientes formatos:

INFO: Public key format: X.509
INFO: Private key format: PKCS#8

En un siguiente blog enseñaré como leer estos archivos, tanto en archivos binario como en texto plano.

Puedes descargar o clonar el código completo de este blog en el siguiente link.

https://github.com/ryctabo/keypair-example-blog

Publicado por

Gustavo Pacheco

Senior Software Engineer

Deja un comentario