Code Monkey home page Code Monkey logo

ejemplo-rsa-java's Introduction

RSA en Java

Static Badge

Un ejemplo básico de uso del algoritmo RSA en Java

Índice

El algoritmo RSA

Algoritmos asimétricos

Los algoritmos asimétricos se caracterizan por utilizar dos claves conectadas:

  • Clave pública: Responsable del cifrado. Es comunicada al emisor del mensaje.
  • Clave privada: Responsable del descifrado. Solo debe conocerla el receptor del mensaje.

Dada la clave privada es posible calcular la clave pública, pero dada la clave pública es imposible calcular la clave privada.

Este sistema es más costoso que los algoritmos simétricos, pero permite la comunicación segura entre emisor y receptor sin haberse puesto de acuerdo previamente en una clave secreta.

Los algoritmos asimétricos pueden utilizarse para intercambiar una clave secreta antes de iniciar la comunicación, por ejemplo:

sequenceDiagram
    actor A 
    actor B
    A->>A: Genera claves<br>pública y privada
    A->>B: Envía clave pública (PK)
    B->>B: Genera clave Secreta (SK)
    B->>B: Cifra SK con PK enviada por A
    B->>A: Envía clave secreta cifrada
    A->>A: Descifra clave secreta <br> con clave privada
Loading

RSA

RSA (llamado así por sus creadores, Rivest, Shamir y Adleman) es un algoritmo de cifrado asimétrico. Fue descrito en 1977 en el MIT. La seguridad de este algoritmo radica en la dificultad de factorizar números grandes.

Ejecución

El programa ha sido desarrollado en IntelliJ IDEA.

  1. Ejecutar la clase Main
  2. Introducir por teclado el mensaje a encriptar
  3. Se mostrará el mensaje encriptado y después el mensaje desencriptado

Explicación

Clases

Clases del JDK

  • Base64: Codificación para transformar una secuencia arbitraria de bytes en una secuencia de caracteres o viceversa.
  • Cypher
  • Clases para entrada/salida (Files, FileOutputStream, FileInputStream)

Clases escritas para el ejemplo

Para visualizar el funcionamiento del algoritmo RSA, en este ejemplo dos clases interactúan encriptando y desencriptando ficheros.

  • Main contiene el método principal y se encarga de la interacción con el usuario.
  • KeyManager genera las claves pública y privada, solo comparte la clave pública para que cualquiera pueda enviarle mensajes encriptados. En una situación real, sería el receptor del mensaje encriptado.
  • EncryptedWriter solo puede cifrar datos porque conoce únicamente la clave pública. En una situación real, sería el emisor del mensaje.

Flujo

La aplicación sigue el siguiente flujo:

  1. KeyManager genera la clave pública y privada
  2. KeyManager escribe la clave pública en un fichero (public.key)
  3. EncryptedWriter recupera la clave pública del fichero
  4. EncryptedWriter cifra los datos con la clave pública y los escribe en un nuevo fichero (encrypted_msg)
  5. KeyManager recupera y descifra los datos del fichero encrypted_msg

Important

Los datos del fichero encrypted_msg son binarios y no se pueden leer abriendo directamente el fichero

Código

Main

El método principal del programa

public static void main(String[] args) {
  KeyManager keyManager = new KeyManager();
  EncryptedWriter encryptedwriter = new EncryptedWriter();
  Scanner scanner = new Scanner(System.in);

  try {
    keyManager.generateKeyPair();       // Genera claves pública y privada
    keyManager.writePublicKey();        // Almacena clave pública en fichero
    encryptedwriter.readPublicKey();    // Lee clave pública almacenada

    System.out.println("Clave pública generada: " +
            Base64.getEncoder().encodeToString(keyManager.getPublicKey().getEncoded()));

    // Obtener entrada del usuario
    System.out.println("Introduce el mensaje secreto");
    System.out.print("> ");
    String userInput = scanner.nextLine();

    encryptedwriter.setSecretMessage(userInput);                // Establece mensaje a encriptar
    byte[] encrypted = encryptedwriter.writeEncryptedMessage(); // Encripta y escribe el mensaje
    String decrypted = keyManager.decryptFile();                // Lee el fichero y desencripta el mensaje

    System.out.println("Mensaje encriptado: " + Base64.getEncoder().encodeToString(encrypted));
    System.out.println("Mensaje desencriptado: " + decrypted);
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

Cifrado

En EncryptedWriter.

Método para cifrar un String y almacenar el mensaje cifrado en un fichero.

/**
 * Escribe el mensaje cifrado en el fichero files/encrypted_msg
 *
 * Escribe directamente los bytes del mensaje encriptado para
 * evitar transformaciones innecesarias a String
 * @return Los bytes del mensaje encriptado, para mostrarlo en el método principal
 * @throws Exception
 */
public byte[] writeEncryptedMessage() throws Exception {
  byte[] messageBytes = secretMessage.getBytes();
  Cipher cipher = Cipher.getInstance("RSA");
  cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  byte[] encryptedBytes = cipher.doFinal(messageBytes);

  Files.createDirectories(Path.of("files")); // Crea el directorio si no existe
  try (FileOutputStream fos = new FileOutputStream("files/encrypted_msg")) {
    fos.write(encryptedBytes); // Escribe los bytes en el fichero
  } catch (IOException e) {
    throw new RuntimeException(e);
  }
    return encryptedBytes;
}

Descifrado

En KeyManager.

Método para desencriptar el fichero encriptado

/**
 * Lee el fichero cifrado y devuelve el mensaje descifrado
 *
 * @return el mensaje descifrado
 */
public String decryptFile() throws Exception {
  File encryptedFile = new File("files/encrypted_msg");
  byte[] encryptedBytes = Files.readAllBytes(encryptedFile.toPath());
  return decrypt(encryptedBytes);
}

/**
 * Descifra un mensaje cifrado
 *
 * @param encryptedBytes Bytes del mensaje encriptado
 * @return El mensaje descifrado
 */
private String decrypt(byte[] encryptedBytes) throws Exception {
  Cipher cipher = Cipher.getInstance("RSA");
  cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); // Clave privada para desencriptar
  byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
  return new String(decryptedBytes, StandardCharsets.UTF_8);
}

Fuentes

ejemplo-rsa-java's People

Contributors

cakeneka avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.