javiermantilla.co

Teniendo en cuenta que PGP es un criptosistema hibrido que combina técnicas de criptografía  simétrica y criptografía asimétrica (https://es.wikipedia.org/wiki/Pretty_Good_Privacy). Y para poder entender gráficamente como funciona dejo el link del siguiente video en YouTube. https://www.youtube.com/watch?v=CHi2RclGvIM.

En la empresa para la que trabajo se requería realizar un programa en java que permitiera descifrar unos archivos enviados por un proveedor de servicios. Este proveedor de servicios tiene el certificado público y la empresa nuestra tiene la llave privada.  Para el ejercicio que voy a mostrar a continuación, se generó el certificado público y la llave de prueba con el programa llamado kleopatra (https://www.gpg4win.org/) GPG4WIN.

javiermantilla.co

Con esta aplicación creamos el certificado y generamos la llave pública y la llave privada

javiermantilla.co

Librerías necesarias  para el funcionamiento de cifrar archivos con certificados PGP. https://www.bouncycastle.org/latest_releases.html, https://mvnrepository.com/artifact/org.bouncycastle

javiermantilla.co

Código java para cifrar:

import pgp.utils.PGPFileProcessor;
/** 
 * @author javiermantilla.co
 */
public class EncriptarPgp {
    public static void main(String[] args) {
        PGPFileProcessor p = new PGPFileProcessor();
        try {
            //Ruta del certificado publico para cifrar
            p.setKeyFile("D:\\pgp\\certificado-llave\\CertificadoPublico.asc");
            //Ruta del Archivo que se va a cifrar
            p.setInputFile("D:\\pgp\\texto-prueba.txt");
            //Ruta del Archivo de salida cifrado
            p.setOutputFile("D:\\pgp\\salida\\final.txt.gpg");
            p.encrypt();
            System.out.println("El archivo se encripto-->"
                    + "D:\\pgp\\salida\\final.txt.gpg");
        } catch (Exception e) {
        }
    }
}

Código para descifrar archivo anteriormente cifrado:

import pgp.utils.PGPFileProcessor;
/** 
 * @author javiermantilla.co
 */
public class DesencriptarPgp {
    public static void main(String[] args) {
        try {
            PGPFileProcessor p = new PGPFileProcessor();
            //Ubicación de la llave privada par descifrar el archivo
            p.setKeyFile("D:\\pgp\\certificado-llave\\llavePrivada.gpg");
            //Clave de la llave privada
            p.setPassphrase("123456");
            //Ubicación del archivo que se va a descifrar
            p.setInputFile("D:\\pgp\\salida\\final.txt.gpg");
            //Ruta del archivo de salida con información legible
            p.setOutputFile("D:\\pgp\\salida\\salida.txt");            
            p.decrypt();
            System.out.println("El archivo se desencripto-->"
                    + "D:\\pgp\\salida\\salida.txt");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Espero que esto nos pueda ayudar y cualquier consulta no dudes en escribirme a ing.javiermantilla@gmail.com

Link para poder descargar los archivos del proyecto. Archivos proyecto

34 Replies to “CIFRAR – DESCIFRAR USUANDO PGP EN JAVA”

  1. Hola , gracias por la publicacion ! ejecute el codigo y le puse los datos de mi llave privada , clave y el archivo encriptado para usar la parte que desencripta pero me da este error: Sabes que puede ser? si lo hago en linux funciona la desencriptacion , pero por app no.

    org.bouncycastle.openpgp.PGPException: org.bouncycastle.openpgp.PGPOnePassSignatureList found where PGPSecretKeyRing expected
    at org.bouncycastle.openpgp.PGPSecretKeyRingCollection.(Unknown Source)
    at PGPUtil.findSecretKey(PGPUtil.java:95)
    at PGPUtil.decryptFile(PGPUtil.java:140)
    at PGPFileProcessor.decrypt(PGPFileProcessor.java:35)
    at DecryptFile.main(DecryptFile.java:16)

  2. Saludos Lucila. Lo que veo en el error es que por lo visto no esta encontrando el archivo de la llave.
    Para salir de dudas, quemale por código la ruta del archivo, para verificar que eso sea y poder descartar. Porque lo que veo es que dice que no encuentra la llave secreta privada..
    Espero poderte colaborar. Buen día

  3. Hola, tengo un problema con la ejecución, desde eclipse funciona todo ok, pero al compilar el jar i lanzarlo java – jar …ejemplo.jar, me da este error en pantalla:

    Caused by: java.lang.ClassNotFoundException: org.bouncycastle.jce.provider.BouncyCastleProvider
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    … 4 more

    Alguna idea?

    Saludos.

  4. como comentario decir que estoy usando jdk 1.8

    Por cierto, perdon que no he dado las gracias, el código está muy bien claro y bien explicado, me ha sido muy util.

    Saludos.

  5. Hola, gracias por tu rápida respuesta, efectivamente ese el problema que tengo, no te había comentado que uso Maven y el STS, y la solcución que comentas en el artículo creo que no me sirve ya que no tengo archivo build.xml.
    No se si debo generarlo nuevo o buscar otra opción.

    Saludos.

  6. Saludos!
    Trata de consultar en san google como generar único archivo jar con maven. o como asignar el path de las librerías necesarias para el proyecto en ejecución. Quedo atento

  7. Hola, solucionado!!!, he probado, con la opción export, runable jar y marcando la opción “package required libreries into generated jar”, ya no me da error con la busqueda de la dependencias.

    Lo que me estaba sacando loco ahora es que desde eclipse se desencripta y todo ok, pero desde windows al lanzar el .jar me estaba dando error ( java.security.InvalidKeyException: Illegal key size), pero me he dado cuenta que lo que pasaba era que eclipse tiraba del JDK con los archivos “local_policy.jar”,.. modifcados y desde el .jar en windows me tiraba del Jre sin cambiar!!!

    Muchas gracias por tu ayuda.

    Saludos

  8. buenas tardes,

    gracias por el codigo, solo que tengo un problema, he bajado las librerias en mi proyecto STS utilizando MAVEN y dentro de la clase PGPUtil.java me da el siguiente error:

    en la linea 49 esta el constructo:
    PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in);
    y me da el siguiente error:

    The constructor PGPPublicKeyRingCollection(InputStream) is undefined

    de antemano muchas gracias por su ayuda,
    saludos

  9. Saludos Ricardo. Las librerías que uso para dicho funcionamiento del proyecto, son las bcpg-jdk16-1.46 –> 16-1.46, de pronto las librerías que se esta descargando por maven son otra versión diferente. A lo mejor dicha versión nueva no tiene dicho constructor. En dicho caso tocaría revisar cómo es que funciona la nueva clase “PGPPublicKeyRingCollection” de la librería que está vinculando en el pom.xml. Este proyecto y código funciona con la librería que 16-1.46.
    Quedo atento.

  10. Que tal amigo me sales estos errores por la clavePGP

    provider nuevapgpcyaal1234 not found.
    java.security.NoSuchProviderException: provider nuevapgpcyaal1234 not found.
    at org.bouncycastle.openpgp.PGPUtil.getProvider(Unknown Source)
    at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(Unknown Source)
    at PGPUtil.findSecretKey(PGPUtil.java:115)
    at PGPUtil.decryptFile(PGPUtil.java:158)
    at PGPFileProcessor.decrypt(PGPFileProcessor.java:34)
    at ProcessCertificate.dencryptFileAccount(ProcessCertificate.java:147)
    at ProcessCertificate.main(ProcessCertificate.java:78)

    Sabes a que se refiere esta variable???
    private static String clavePGP = “nuevapgpcyaal1234”;

    Se utiliza en este metodo:

    private static PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass)
    throws IOException, PGPException, NoSuchProviderException
    {
    PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn));
    PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);

    if (pgpSecKey == null)
    return null;

    //pgpSecKey.extractPrivateKey(arg0) //**
    return pgpSecKey.extractPrivateKey(pass, clavePGP);
    }

    *clavePGP no se que parametro es, te mande correo quisiera ver tu clase PGPUtil.java

    Saludos

  11. Saludos David..
    Te respondi el correo con el proyecto adjunto, de las clases utilizadas y los jar necesarios.
    Quedo atento

  12. Buen día Javier

    Muchas gracias por el correo

    Ya vi el la clase PGPUtil.java y ya resolvi el error, solo era comparar la siguiente linea

    return pgpSecKey.extractPrivateKey(pass, “BC”);

    “BC” en el proyecto se esta utilizando para encriptar y desencriptar y en el mio no lo tenia así pero ya funciono con este cambio.

    Saludos amigo y muchas gracias

  13. Hola, cuando se quiere firmar un token o un “desafío” de una response de un servicio rest, el navegador, por ejemplo Chrome, recibe la response del servidor, se abriría el popoup con los certificados instalados en dicho navegador, se seleccionaria uno y mi duda viene ahora, la firma de algo q venga en el “response” (un token, un desafío o lo que sea) se realiza por parte del navegador automáticamente? Como se realiza ese proceso?

    Gracias

  14. Saludos Juanjo, Nunca he hecho las pruebas, pero en teoría la firma de algo que viene en el “response” lo ha realizado el certificado del servidor, que es completamente diferente a firmar un archivo o texto con el utilitario PGP, directamente desde java.
    Quedo atento y buen día

  15. Hola Javier, Hice la cifrado y todo ok, pero al intentar descifrar me lanza errores:

    xx.PGPUtil.findSecretKey(PGPUtil.java:104)
    xx.PGPUtil.decryptFile(PGPUtil.java:141)
    xx.PGPFileProcessor.decrypt(PGPFileProcessor.java:35)
    …..
    Caused by: java.security.NoSuchAlgorithmException: No such algorithm: AES/CFB/NoPadding
    at javax.crypto.Cipher.getInstance(Cipher.java:687)

    Al parecer es un problema con la contraseña, el mismo archivo cifrado lo llevo a Kleopatra y me descifra correctamente y con la misma contraseña, que puede estar fallando?

  16. Saludos Wilmer. El problema que veo es que no esta encontrando el archivo que tiene la llave secreta. Si quiere mejor haga la prueba colocándole la ruta completa al archivo para salir de dudas. Osea colocar por ejemplo: “C://archivo/…..”
    Quedo atento y Buen día.

  17. Estimado Javier, Lo que pasó fue que mi computador tuvo un apagón, mientras estaba encedida Eclipse, al parecer esto causó daños en el mismo eclipse que impedía funcione bien el descifrado. Reinicié el equipo, y todo funcionó bien. Gracias.

  18. Hola, ¡muchas gracias!, por el código y por las especificaciones a la hora de explicar cómo funciona el procedimiento del ejemplo, de verdad es de resaltar a quienes ayudan de esta manera 🙂

  19. Buenos días.

    Tengo el siguiente error al implementar el codigo en netbeans y eclipse.

    Exception in thread “AWT-EventQueue-0” java.lang.ExceptionInInitializerError
    at org.bouncycastle.jcajce.provider.digest.GOST3411$Mappings.configure(Unknown Source)
    at org.bouncycastle.jce.provider.BouncyCastleProvider.loadAlgorithms(Unknown Source)
    at org.bouncycastle.jce.provider.BouncyCastleProvider.setup(Unknown Source)
    at org.bouncycastle.jce.provider.BouncyCastleProvider.access$000(Unknown Source)
    at org.bouncycastle.jce.provider.BouncyCastleProvider$1.run(Unknown Source)

  20. Saludos rafael!
    El poblema que veo es que no esta encontrando la libreria, el jar cuando lo esta empaquetando. verifique que efectivamente la libreria este en la carpeta lib del proyecto.
    Espero con esto colaborarte. Buen día.

  21. Hola,
    Muchas gracias, excelente ejemplo, me funciona al cifrar archivos mediante llave publica *.asc, pero al intentar cifrar el mismo archivo con una llave publica *.pgp me genera el archivo vacío (0 KB), alguna idea? para cifrar con otras llaves *.pgp, *.pgpkey el código es diferente?

  22. Hola,
    Excelente ejemplo muchas gracias, me funciona ok con llave pública .asc, sin embargo al tratar cifrar con llave pública .pgp me genera archivo vacío (0 KB) , alguna idea? Este código sirve para cifrar con cualquier extensión de llave publica?

  23. Saludos Jorge!. La verdad es que pensaria que si.. de momento solo hice esa prueba con ese tipo de archivo. Pero la verdad con los otros tipos de llaves no he realizado pruebas. Seria googlear para ver como es que se cifra con ese tipo de llaves y que libreria es la que serviria. Buen día

  24. Saludos Jorge!. La verdad es que pensaria que si.. de momento solo hice esa prueba con ese tipo de archivo. Pero la verdad con los otros tipos de llaves no he realizado pruebas. Seria googlear para ver como es que se cifra con ese tipo de llaves y que libreria es la que serviria. Buen día

  25. buenas amigo gracias por tu aporte, estoy intentando descargar los archivos del proyecto pero no puedo acceder al link, si me puedes ayudar muchas gracias!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *