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.
Con esta aplicación creamos el certificado y generamos la llave pública y la llave privada
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
Código java para cifrar:
import pgp.utils.PGPFileProcessor; /** * @author javiermantilla.work */ 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--gt;" + "D:\\pgp\\salida\\final.txt.gpg"); } catch (Exception e) { } } }Código para descifrar archivo anteriormente cifrado:
import pgp.utils.PGPFileProcessor; /** * @author javiermantilla.work */ 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--gt;" + "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. https://github.com/jmantillap/cifrado-descifrado-pgp
Muchas gracias por la información y del código
Con gusto. Para eso estamos. El conocimiento es libre.
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)
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
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.
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.
No esta encontrando la librería. lo que le recomiendo es empaquetar todo en un único *.jar
http://www.javiermantilla.work/empaquetando-unica-libreria/
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.
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
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
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
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.
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
Saludos David..
Te respondi el correo con el proyecto adjunto, de las clases utilizadas y los jar necesarios.
Quedo atento
En el post esta tambien el link del proyecto.
https://drive.google.com/open?id=0BzfJqCIE0Bmpa24tNzI4ZTFVd1U.
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
Ok. me alegra saber que lo pudo solucionar. un abrazo y para eso estamos. buen día
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
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
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?
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.
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.
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 🙂
Ok. Perfecto. Que tengas buen día.
Estimado Juan. Saludos y para eso estamos.
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)
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.
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?
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?
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
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
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!
Saludos Simon!
Ya te envio los archivos al correo sasalazar3@gmail.com.
Buen día
Se envio Archivo al correo. sasalazar3@gmail.com
Doc gracias por tu aporte, estoy intentando descargar los archivos del proyecto pero no puedo acceder al link, si me puedes ayudar muchas gracias!
Doc gracias!, estoy intentando replicarlo, pero los archivos del proyecto no se pueden acceder, si me puedes ayudar muchas gracias!
Buenas tardes jose. ya se los envio al correo. buen dia
Saludos jose. Te los envie por wettranfer. Buen día y bendiciones
Buen dia,
Estoy utilizando la función para cifrar y cuando lo ejecuto desde netbeans esto funciona perfectamente, pero cuando genero un archivo .jar con mi proyecto al momento de cifrar un grupo de archivos estos quedan en 0.kb y arroja el error por consola de exception encrypting session key.
Agradeceria mucho su ayuda si tiene conocimiento de como podría dar solución a este error, muchas gracias de antemano.
Hola moises. Disculpe que hasta ahora conteste.. la verdad depronto lo que hace falta es que cuando generes el *.jar, generes un unico jar, como se explica en el post. http://www.javiermantilla.work/empaquetando-unica-libreria/
Generar un unico jar con las dependencias o librerias que tiene el proyecto. Quedo atento y cualquier cosa me escribes a jmantillap@gmail.com.
Hola, tengo un problema, he importado una llave pública, ésta aparece en la lista de llaves de kleopatra, pero cuando quiero encriptar un archivo con la llave de esta persona, la llave no aparece más, incluso cambie el nivel de confianza para ver si así podía encriptar para esta persona pero no funciona. No se si me falta algún proceso para encriptar? porque no podría encriptar un archivo si tengo la llave pública?
Gracias
Hola Stephanie, Cual error es exactamente el que te aparece. Cualquier cosa lo podriamos ver, si necesitas una conferencia para ver exactamente el problema. mi correo es jmantillap@gmail.com. quedo pendiente
Me arroja esta Excepción pero no se a que se deba …
org.bouncycastle.openpgp.PGPException: Encrypted message contains a signed message – not literal data.
Podrias compartirme las fuentes, me indica que no tengo acceso :/
Gracias de antemano
https://github.com/jmantillap/cifrado-descifrado-pgp
Que tal, me arroja la siguiente excepción al desencriptar un archivo externo, me compartieron la llave privada y la contraseña pero me arroja el siguiente mensaje
java.io.IOException: unknown packet type encountered: 20
Espero me puedas ayudar
Saludos.!!
org.bouncycastle.openpgp.PGPException: Encrypted message contains a signed message – not literal data.
Ese error me sale, alguien ha encontrado la solución. Ya que quiero decifrar archivos txt
org.bouncycastle.openpgp.PGPException: Encrypted message contains a signed message – not literal data.
Me sale ese error alguien ha encontrado la solución?
Hola carlos, si no has podido encontrar la solución, contactame por meet. jmantillap@gmail.com
Hola carlos, si no has podido encontrar la solución, contactame por meet. jmantillap@gmail.com
Hola Mario, si no has podido encontrar la solución, contactame por meet. jmantillap@gmail.com, Para ver como te puedo colaborar