Esta es una clase que permite generar juego de claves, guardarlas y por supuesto cifrar y descifrar, esta diseñada para Java SE ya que las funciones para guardar y recuperar las claves desde el disco no son compatibles con Android, si  necesitan esta clase para Android pueden ir al articulo Encriptar y Desencriptar con RSA en ANDROID sino pueden seguir viendo Encriptar y Desencriptar con RSA en JAVA

Primero como usamos la clase:

public class main {
    
    public static void main(String[] args) throws Exception {
        
        
        //Definimos un texto a cifrar
        String str = "Este es el texto a cifrar";
        
        System.out.println("\nTexto a cifrar:");
        System.out.println(str);
        
        //Instanciamos la clase
        RSA rsa = new RSA();
        
        //Generamos un par de claves
        //Admite claves de 512, 1024, 2048 y 4096 bits
        rsa.genKeyPair(512);
        
        
        String file_private = "/tmp/rsa.pri";
        String file_public = "/tmp/rsa.pub";
        
        //Las guardamos asi podemos usarlas despues
        //a lo largo del tiempo
        rsa.saveToDiskPrivateKey("/tmp/rsa.pri");
        rsa.saveToDiskPublicKey("/tmp/rsa.pub");
        
        //Ciframos y e imprimimos, el texto cifrado
        //es devuelto en la variable secure
        String secure = rsa.Encrypt(str);
        
        System.out.println("\nCifrado:");
        System.out.println(secure);
        
                
        
        //A modo de ejemplo creamos otra clase rsa
        RSA rsa2 = new RSA();
        
        //A diferencia de la anterior aca no creamos
        //un nuevo par de claves, sino que cargamos
        //el juego de claves que habiamos guadado
        rsa2.openFromDiskPrivateKey("/tmp/rsa.pri");    
        rsa2.openFromDiskPublicKey("/tmp/rsa.pub");
        
        //Le pasamos el texto cifrado (secure) y nos 
        //es devuelto el texto ya descifrado (unsecure) 
        String unsecure = rsa2.Decrypt(secure);
        
        //Imprimimos
        System.out.println("\nDescifrado:");
        System.out.println(unsecure);   
        

        
    }
    
    

}

La salida que produce el codigo anterior:

Texto a cifrar:
Este es el texto a cifrar

Cifrado:
19q1c3rn9p9rfnquycflpfqu0kv1rggv1wbtbvdkye2lwdi4lkoof2v3spgp768lbchd0g2qexl7t5csif8d8s5w574u79126pbz

Descifrado:
Este es el texto a cifrar


Por ultimo la clase RSA.java que hace todo:

import java.io.BufferedReader;
import java.io.BufferedWriter;

import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;

import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class RSA {
    
    public PrivateKey PrivateKey = null;
    public PublicKey PublicKey = null;

    public RSA()
    {
        

    }
    
    public void setPrivateKeyString(String key) throws NoSuchAlgorithmException, InvalidKeySpecException{
        byte[] encodedPrivateKey = stringToBytes(key);
        
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
        PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
        this.PrivateKey = privateKey;
    }

    public void setPublicKeyString(String key) throws NoSuchAlgorithmException, InvalidKeySpecException{
        
        byte[] encodedPublicKey = stringToBytes(key);
        
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
        PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
        this.PublicKey = publicKey;
    }

    public String getPrivateKeyString(){
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(this.PrivateKey.getEncoded());
        return bytesToString(pkcs8EncodedKeySpec.getEncoded());
    }

    public String getPublicKeyString(){
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(this.PublicKey.getEncoded());
        return bytesToString(x509EncodedKeySpec.getEncoded());
    }
    
    
    public void genKeyPair(int size) throws NoSuchAlgorithmException,NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException  {
        
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(size);
        KeyPair kp = kpg.genKeyPair();
        
        PublicKey publicKey = kp.getPublic();
        PrivateKey privateKey = kp.getPrivate();
        
        this.PrivateKey = privateKey;
        this.PublicKey = publicKey;
    }

    public String Encrypt(String plain) throws NoSuchAlgorithmException,NoSuchPaddingException, InvalidKeyException,IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, UnsupportedEncodingException, NoSuchProviderException {

        byte[] encryptedBytes; 
  
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, this.PublicKey);
        encryptedBytes = cipher.doFinal(plain.getBytes());

        return bytesToString(encryptedBytes);

    }

    public String Decrypt(String result) throws NoSuchAlgorithmException,NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

        byte[] decryptedBytes;

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, this.PrivateKey);
        decryptedBytes = cipher.doFinal(stringToBytes(result));
        return new String(decryptedBytes);
    }

    public String bytesToString(byte[] b) {
        byte[] b2 = new byte[b.length + 1];
        b2[0] = 1;
        System.arraycopy(b, 0, b2, 1, b.length);
        return new BigInteger(b2).toString(36);
    }

    public byte[] stringToBytes(String s) {
        byte[] b2 = new BigInteger(s, 36).toByteArray();
        return Arrays.copyOfRange(b2, 1, b2.length);
    }


    public void saveToDiskPrivateKey(String path) throws IOException {
        try {
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path), "UTF-8"));
            out.write(this.getPrivateKeyString());
            out.close();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
    
    public void saveToDiskPublicKey(String path) {
        try {
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path), "UTF-8"));
            out.write(this.getPublicKeyString());
            out.close();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    public void openFromDiskPublicKey(String path) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        String content = this.readFileAsString(path);
        this.setPublicKeyString(content);
    }
    
    public void openFromDiskPrivateKey(String path) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        String content = this.readFileAsString(path);
        this.setPrivateKeyString(content);
    }
    
    
    private String readFileAsString(String filePath) throws IOException {
        StringBuffer fileData = new StringBuffer();
        BufferedReader reader = new BufferedReader(
                new FileReader(filePath));
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
        }
        reader.close();
        return fileData.toString();
    }
        
}


42 comments

  1. Hola:

    Después de casi dos años … una pregunta.
    Modifiqué main() para separar encripción y desencripción en dos clases distintas que se “comunican” a través de files en disco.

    Se supone que debería poder desencriptar con clave pública, pero no es así.
    Copio los dos main modificados que no funcionan (bueno, el de desenciptar solo). En el main de desencripción está comentada la parte de clave privada y habilitada la parte de clave pública y no funciona.
    Espero que se entienda la duda.
    ———————————————————————————
    Main para encriptar
    ******************
    public static void main(String[] args) throws Exception {

    //Definimos un texto a cifrar
    String str = “Este es el texto a cifrar, OK ??”;
    System.out.println(str);

    //Instanciamos la clase
    RsaEncripta rsa = new RsaEncripta();

    //Generamos un par de claves
    //Admite claves de 512, 1024, 2048 y 4096 bits
    rsa.genKeyPair(512);

    //Las guardamos asi podemos usarlas despues
    //a lo largo del tiempo
    // rsa.saveToDiskPrivateKey(“C:/tmp/rsa.pri”);
    rsa.saveToDiskPublicKey(“C:/tmp/rsa1.pub”);

    //Ciframos y e imprimimos, el texto cifrado
    //es devuelto en la variable secure
    String secure = rsa.Encrypt(str);

    System.out.println(“\nCifrado:”);
    System.out.println(secure);
    RandomAccessFile encriptado = new RandomAccessFile (“c:\\tmp\\encriptado.txt”, “rw”);
    encriptado.writeBytes(secure);
    encriptado.close();
    }
    —————————————————————————————-
    Main para desencriptar
    ******************
    public static void main(String[] args) throws Exception {
    String secure = “”;
    String str = “”;

    RandomAccessFile encriptado = new RandomAccessFile (“c:\\tmp\\encriptado.txt”, “rw”);
    secure = encriptado.readLine();
    encriptado.close();
    System.out.println(secure);

    //A modo de ejemplo creamos otra clase rsa
    RsaDesEncripta rsa2 = new RsaDesEncripta();

    //A diferencia de la anterior aca no creamos
    //un nuevo par de claves, sino que cargamos
    //el juego de claves que habiamos guadado
    // rsa2.openFromDiskPrivateKey(“C:/tmp/rsa.pri”);
    rsa2.openFromDiskPublicKey(“C:/tmp/rsa.pub”);

    //Le pasamos el texto cifrado (secure) y nos
    //es devuelto el texto ya descifrado (unsecure)
    String unsecure = rsa2.Decrypt(secure);

    //Imprimimos
    System.out.println(“Descifrado:”);
    System.out.println(unsecure);
    }

    1. Hola Ignacio, en realidad es al revés, cifras con la pública y descifras con la privada, si descifraras con la pública cualquiera podría hacerlo ya que es pública, lo que garantiza la seguridad de los datos es que la clave para descifrar es que realmente sea privada para que sólo tu lo puedas decifrar el mensaje codificado, prueba con la privada en la segunda clase, espero que sea de ayuda y cualquier consulta me avisas quedo a las órdenes.

  2. Muchas gracias por tu respuesta Alvaro.

    Efectivamente, ahora si funciona con el cambio de roles.

    Yo estaba pensando en un escenario distinto, donde yo envío un texto encriptado con clave privada y el destino desencripta con una pública y por lo tanto conocida. De esta manera saben que el originario sin duda soy yo, el conocedor de la clave privada.

    Saludos
    Ignacio

    1. Hola Ignacio, te comprendo, lo que puedes hacer es renombrar las funciones, que la llamemos publica o privada es un tanto arbitrario, en realidad una cifra y la otra descifra, si intercambias los nombres de pública por privada y privada por pública la función de cada una no cambia en realidad y se ajustaria mejor a lo que necesitas, Saludos y a la ordenes

      1. Hola Alvaro.

        El código de tu página es muy bueno, hubieron partes que me fueron de mucha utilidad, las adapté a un ejemplo que hice. Sólo me gustaría comentarte que la idea que tenía Ignacio era correcta, es posible cifrar con la llave privada y descifrar con la pública, de hecho la idea es que principalmente puedas realizarlo de ese modo (aunque también se puede realizar de manera inversa), ya que al cifrar un texto o contraseña envías los datos cifrados y la llave pública para que el receptor pueda descifrarlo, la garantía de seguridad en este concepto es que solo el receptor podrá hacerlo ya que es el único que tiene la llave pareja.

        Como mencioné anteriormente tambíen es posible hacerlo de manera inversa, ya que la persona que tiene la llave pública a su vez puede cifrar algo y enviarlo, en este caso el receptor(llave privada) es el único que podrá descifrarlo.

        Muchas gracias.
        Hasta pronto.

        1. Hola Oscar

          Muchas gracias por tu comentario, en realidad sobre la posibilidad de cifrar con la llave privada y descifrar con la publica si bien se puede hacer esta mal hacerlo así, es inseguro por donde lo mires

          Para cifrar solo se debe hacer con una llave publica ¿De quien? Y ahí es donde esta el tema, para enviarle algo a alguien no lo haces con tu clave publica sino con la que esa persona te debe proporcionar, la cosa funciona asi, si tu quieres enviarle algo cifrado a alguien lo que debes hacer es pedirle su clave publica, cifrar el mensaje con ella y enviarle el texto cifrado y solamente esa persona puede descifrarlo con su clave privada.

          Para que esa persona te conteste, tu debes enviarle tu clave publica, para que el cifre la respuesta con esa clave y solo tu podrás descifrarla con tu clave privada.

          Básicamente, para establecer una comunicación se deben intercambiar llaves publicas, cada uno va a cifrar el mensaje con la clave publica del otro (nunca con la propia) y cuando se reciban mensajes cifrados se descifran con la privada de cada uno.

          La idea de la clave publica es que sea publica, que pueda tenerla cualquier persona, de hecho hay servidores de claves publicas, ¿De que te sirve cifrar algo que cualquier puede decifrarlo con la calve publica que cualquiera puede obtener por ser justamente publica?

          En resumen, cuanto tu envíes debes cifrarlo con la clave publica de la otra persona y tu si debes enviar tu clave publica pero no para que descifren el contenido sino para que te contesten con contenido cifrado, la clave de decifrado (que es la privada) nunca debe ser transmitida a ningún lado ya que por eso es privada, porque solo debe ser usada por la persona que la genero

          Espero que haya quedado un poco mas claro

          1. Muchas gracias Alvaro.
            No lo había visto desde esa perspectiva, como mencionas es más seguro.
            Saludos.

  3. Voy a probar ese cambio.
    Alvaro:

    Creo que entiendo el concepto… La pública finalmente es la que hago conocer (o hago pública, claro).

    Sin embargo (perdon por mi ignorancia) veo que la clave privada que genera la clase es bastante mas larga que la pública. Tiene sentido hacer el cambio de roles y usar una clave privada mas corta que la pública ? Tendría que hacer un cambio en los métodos, no ?.

    Voy a probar de intercambiar las funciones y veo …

    Slds
    Ignacio

    1. Hola Ignacio, el largo de la clave es debido a la función que cumple cada una.

      Originalmente esta pensado para que alguien cifre datos con la pública y que solo sean descifrados por la clave privada, en tu caso por lo que entendí lo que quieres hacer es al revés, simplemente estarías invirtiendo los roles, solo tienes que invertír el nombre de los métodos.

      Aunque la verdad no se que tan seguro será, en el código original teniendo la clave pública nunca puedes averiguar la privada, lo que no se, si teniendo la privada puedes obtener la pública, si esto fuera así y si tu estubieras distribuyendo la privada y podrian averiguar la pública y cualquiera podría cifrar por ti, es un tema complejo, entiendo los conceptos, el funcionamiento y su implementacion pero la verdad no soy criptografo para comprender el algoritmo matemático de fondo y la conveniencia de invertir las claves.

      Hay un libro sobre este tema que te puedo ayudar, yo lo tengo pero aviso que no es muy sencillo de leer
      https://0xword.com/es/libros/36-libro-cifrado-comunicaciones-rsa.html

  4. Hola Alvaro!

    Puedo cifrar un documento XML usando AES256 y la llave que valla cifrada dentro de este mismo documento pero usando RSA SHA256

  5. Hola Alvaro, la clase RSA tu la creaste? Podrias explicarla un poco por favor, para entender mejor este algoritmo RSA ya wue ko lo alcanzo a comprender.

    Saludos y gracias pr tu apoyo

    1. Hola.

      La clase la cree yo si, igualmente poco para explicar sobre RSA en mismo ya que la clase simplemente encapsula ciertas operación sobre las librerías java para cifrado, que son la que realmente hacen el trabajo.

      La clase que yo escribí lo único que hace es usar las librerías para generar las claves y luego usarlas para cifrar y descifrar los datos de forma más sencilla, como funciona RSA mismo está dentro de estas librerías y no en la clase que yo escribí.

      Si quieres aprender sobre como funciona RSA hay un libro sobre este tema que te puedo ayudar:
      https://0xword.com/es/libros/36-libro-cifrado-comunicaciones-rsa.html

      Saludos

  6. Exception in thread “main” java.io.FileNotFoundException: \tmp\rsa.pri (El sistema no puede encontrar la ruta especificada)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.(FileInputStream.java:138)
    at java.io.FileInputStream.(FileInputStream.java:93)
    at java.io.FileReader.(FileReader.java:58)
    at RSA.readFileAsString(RSA.java:151)
    at RSA.openFromDiskPrivateKey(RSA.java:144)
    at main.main(main.java:43)
    C:\Users\——-\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
    BUILD FAILED (total time: 0 seconds)

    1. Hola Jefferson

      Por el error tiene un problema con la ruta \tmp\rsa.pri cambia la ruta a una ruta valida y el error debería desaparecer, por la orientación de las barras usas Windows así que la ruta debería ser algo como C:\\tmp\rsa.pri solo asegúrate que el directorio exista porque la ruta original del código esta destinado a un sistema de archivos Linux donde si existe la ruta /tmp

      Saludos

  7. ¿Cómo podemos obtener el equivalente de este código en c#?, para poder comunicar un programa en java con esta encriptación (web service) y otro programa en C# (cliente de escritorio), el problema que veo en c#, es que los códigos que ido encontrando usan las claves privadas y públicas con un formato en xml, que no es texto directamente como las creadas aquí (*.pri y *.pub). ¿Cómo podríamos tener el mismo código en c#?.

    1. Hola Santiago, está codigo esta muy atado a Java ya que utiliza librerías de java mismo como java.security.* y javax.crypt.* por lo que utilizar el mismo código sería imposible,

      Igualmente si ya tienes funcionando otros ejemplos en C# y lo único que necesitas es que queden como texto puedes utilizar convertir a base64 y te queda como cadena de texto igual que las de este código y no xml, luego al leer las claves como texto las decodificar nuevamente para convertirlas en xml y poder cifrar y/o descifrar.

      Recuerda que la clave que vos ves no es una cadena aleatoria, son datos (como un xml) convertidos a base64, lo ideal es guardarlas en disco en base64 y al leerlas decodificarlas y que te queden en xml o como tu código necesite y así trabajar con ellas.

      Espero que te se de ayuda

  8. Buenas Álvaro, estoy tratando de hacer un servidor el cual varios clientes le envíen archivos y encripte/desencripte dichos archivos.
    Para empezar he intentado hacer funcionar tu código pero no lo consigo, me sale el siguiente error:
    Texto a cifrar:
    Este es el texto a cifrar

    Cifrado:
    1bk9so3kkxeb49hamyalmxwffqgz2pr8avpkwb49uhjo8dlxfdfzykyukyozi83gb548jgzpc1f1klls52xsep433dqw7c0m1cns
    java.io.FileNotFoundException: C:\tmp
    sa.pri (El nombre de archivo, el nombre de directorio o la sintaxis de la etiqueta del volumen no son correctos)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(Unknown Source)
    at java.io.FileInputStream.(Unknown Source)
    at java.io.FileInputStream.(Unknown Source)
    at java.io.FileReader.(Unknown Source)
    at Principal.RSA.readFileAsString(RSA.java:150)
    at Principal.RSA.openFromDiskPrivateKey(RSA.java:142)
    at Principal.Principal.main(Principal.java:57)

    La línea 57 es esta: rsa2.openFromDiskPrivateKey(“C:\\tmp\rsa.pri”);
    ¿En el directorio tmp tendría que tener algo? Y realmente me aconsejas usar el método RSA para un servidor con la función previamente indicada?
    También me pasaba el mismo error que a Jefferson pero creo que lo he solucionado poniendo como tu dijiste la ruta bien (C:\\tmp\rsa.pri y C:\\tmp\rsa.pub), pero no consigo que funcione el código, ¿a que se puede deber?

    1. Hola Sergio

      ¿En el directorio tienes los archivos rsa.pri y rsa.pub? Por el mensaje parece que las claves no están en el lugar que le indicas, asegurate de crearlas con la función rsa.genKeyPair(2048), asegurate que tengas permisos de escritura en el directorio

      Saludos

      1. Buenas Alvaro,
        si no he entendido mal el programa, las claves las genera automaticamente cuando se usa la funcion rsa.genKeyPair(2048). Lo que hice fue crear en mi disco duro C una carpeta llamada tmp, pero está vacía,¿debería crear algo mas?
        Y perdona por repetirme ,pero, realmente es útil este método en una aplicaciçon cliente-servidor cuando lo que quiero es que el cliente le envíe un archivo al servidor y sea el servidor quien le devuelva dicho fichero pero cifrado.

        1. Hola Sergio

          Si correcto, es genKeyPair la función que genera las claves aunque las deja en memoria, después llama a rsa.saveToDiskPrivateKey(/ruta) y rsa.saveToDiskPublicKey(/ruta) para almacenarlas en el disco, si después de llamar a estas funciones no te las guardo seguramente tengas un problema de permisos, asegurate que el programa pueda escribir en el directorio.
          Saludos

          1. Hola Álvaro,
            ya he conseguido que funcione, a la hora de trasladarlo a mi problema, encriptar lo hace bien, pero si el cliente le pasa el archivo que previamente ha encriptado para desencriptarlo me salta la siguiente excepción:
            javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes
            at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:344)
            at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
            at javax.crypto.Cipher.doFinal(Cipher.java:2164)
            at Principal.RSA.Decrypt(RSA.java:100)
            at Principal.Servidor.main(Servidor.java:52)

          2. Hola Sergio
            ¿Y el cliente con que llave cifro? ¿Con una tuya o con una que genero el? Ten en cuenta que tu debes tener la llave para descifrar el archivo que te pasen, tu debes generar tu claves, pasar la publica al cliente para que cifre los archivos que luego tu descifraras con tu llave privada.
            Saludos

  9. Buenas Álvaro,
    mi aplicación consiste en que el cliente “es tonto” y no sabe hacer nada más que mandarle el archivo al servidor, ya sea encriptado (que si es el encriptado es porque previamente lo ha tenido que mandar al servidor para que se lo encripte) o desencriptado. Es decir, que lo hace todo el servidor.

    1. Ya he conseguido arreglarlo, pero cuando le paso un archivo muy grande me sale lo siguiente:
      javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes
      at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:344)
      at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
      at javax.crypto.Cipher.doFinal(Cipher.java:2164)
      at Principal.RSA.Encrypt(RSA.java:88)
      at Principal.HiloCliente.run(HiloCliente.java:48)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
      at java.lang.Thread.run(Unknown Source)

      ¿Como lo soluciono?

      1. Hola Sergio

        Si el archivo es muy grande es posible que estés teniendo problemas de memoria o puede que el método de cifrado no sea adecuado para archivos, por el mensaje indica que los datos no deben exceder los 256 bytes, de hecho el código no lo programe pensando en cifrar archivos sino mensajes o textos cortos y para eso me ha funcionado de maravilla, el error que te da no se si eso es por el algoritmo de cifrado inadecuado para lo que necesitas, por alguna modificación que hayas podido hacer o simplemente por el largo de la llave, por las dudas revisa el largo de bits que estas usando, que sea de 2048 o 4096 bits.

        Saludos

  10. Hola Alvaro, estoy intentando implementar el código para que en lugar de tener un texto pre-definido para encriptar, mas bien hacer que el código reciba un texto como parametro de metodo, he intentado hacerlo creando un metodo que reciba como parametro el texto a cifrar pero a la hora de ejecutarlo no pasa nada (me imagino que es porque no se encuentra dentro del metodo main), como debería modificar el código para que funcione?

    1. Hola Jordano

      Sin ver el código o como lo tienes implementado no tengo manera de saber porque no funciona y mucho menos puedo recomendarte que deberías modificar para que funcione, lo que si puedo decirte es lo básico y es que tienes que instanciar y llamar a la clase desde un fragmento de código que se ejecute previo a lo que quieres, idealmente desde el constructor de la clase principal del objeto que estés cargando.

      Saludos

  11. Hola Alvaro.
    Estoy intentando implementar la clase RSA pero obtengo una excepción zero lenght BigInteger en la línea
    byte[] b2 = new BigInteger(s, 36).toByteArray() del método stringToBytes.
    ¿Alguna ayuda? Gracias de antemano.

    1. Hola Felix

      La función tiene un solo parámetro de entrada por lo que el problema es el valor que le estes pasando como parámetro, la función recibe un string, asegurate que lo que le estes pasado sea verdaderamente un string y no un valor null o empty.

      Saludos

      1. Hola Álvaro.
        Ante todo muchas gracias por responder. Ya está solucionado. Me faltaba cerrar el flujo del método que salva la clave pública en el disco.
        Un saludo.

  12. Hola una consulta y esto se peude hacer en base a certificados genrados en OpenSSl en vez d egenrarlo con el genKey se puede usar un certificado generaod en OpenSSl con rsa y clave de 2048 en vez de usar la genración de la clave en la misma clase Java, yo he intentado con archivos de OpenSSl, con esa cantidad de clave de 2048 pero da erro igual usando clave publica y privada.
    Muchas gracais
    Saludos

    1. Hola Manuel

      En realidad son 2 cosas diferentes, lo que generas con OpenSSL es un Certificado SSL autofimado o un CSR para validar un SSL real (no un autofirmado) emitido por una certificadora como Comodo/Sectigo, GeoTurst, RapidSSL, etc, con OpenSSL no generas un par de claves de cifrado que es lo que realmente necesitas, si bien OpenSSL te da una llave privada en ningún momento te da una llave pública sino un CRT o un CSR dependiendo de lo que le pidas, ninguno de los dos (ni CRT ni CSR) funcionan como claves públicas, no son para eso, no es su función.

      Saludos

  13. Hola Alvaro, mira estoy usando lo que indicas en el código y me encripta bien pero me esta saliendo error es desencriptando.

    javax.crypto.BadPaddingException: Decryption error
    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:370)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:282)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:370)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:404)
    at javax.crypto.Cipher.doFinal(Cipher.java:2168)
    at co.com.avh.certification.forwarder.utils.ChangePrivateKeys.Decrypt(ChangePrivateKeys.java:98)
    Te agradezco si me puedes ayudar.

    1. Hola Alexsabder

      ¿Conoces la frase? “Cuando escribí esto sólo Dios y yo sabíamos como funcionaba. Ahora, sólo Dios sabe.” bueno, esto es más o menos asi, esto lo publique hace 5 años y el codigo era por lo menos el doble de viejo así que mucho no recuerdo de él, igualmente por el tipo de error supongo que el tema está en la generación de las claves, o no se genero correctamente la llave privada o no estas utilizando la llave privada sino la pública, asegurate de que estés usando la clave privada para desencriptar y que esta tenga contenido, es decir que no este llegando vacía, saludos.

      1. Hola Alvaro buenas tardes! Tu ejemplo me ayudo mucho, solo una pregunta. Donde o como se ponen las llaves publicas? Ya que estoy haciendo una aplicacion de escritorio donde me solicitaron mandar una cadena de json con campos a encriptar, cosa que la aplicacion ya hace, pero me falta la parte del public key. Espero puedas ayudarme.
        Saludos!

        1. Hola Jose

          Muchas gracias por tu comentario, para generar las llaves tienes en la clase la función genKeyPair y para guardarlas las funciones saveToDiskPrivateKey y saveToDiskPublicKey, igualmente recuerda que para intercambiar mensajes cifrados entre dos puntos, ambos deben intercambiar llaves públicas, el cifrado se debe hacer con la llave publica del otro.

          Saludos

Leave a Reply

Your email address will not be published. Required fields are marked *

Discover more from Alvaro De León

Subscribe now to keep reading and get access to the full archive.

Continue reading