PGP Encryption using Bouncy Castle

It can’t be that hard. So given a couple hours of hacking with the library, here’s a fully illustrated example that shows how to encrypt a file using the Bouncy Castle Cryptography API and PGP. First, giving credit where credit is due, the example comes mostly from the KeyBasedFileProcessor example that ships with the Bouncy Castle PGP libraries. You can find it in the /src/org/bouncycastle/openpgp/examples directory if you download the source. I’ve simply unpacked the example a little, providing some pretty pictures and explanation of what the various pieces are.

As in any example, you need to have downloaded a couple libraries; in this case you need to visit http://www.bouncycastle.org/latest_releases.html and download the bcprov-jdk14-122 and bcpg-jdk14-122 jar files. Add those to your project, as in this example, simply make sure to add them to the classpath when running the example from the command line.

Next, while you don’t need to have PGP installed, you do need to have a at least one public keyring file available on your system. I’m using PGP 6.5.8 on Windows which automatically saves my public keyring for me. You can find the location of the keyring file by Edit –> Options –> Files from within the PGP Keys window. You should see something like this:
PGP Options
Note the location of the Public Keyring File.

Second, you’ll need to generate a keypair (if you don’t already have one). I won’t go into the how or why (I assume you know the how and why) but you do need to make sure that you create what the Bouncy Castle folks call a ‘RSA key’ or ‘El Gamal key’ (source) rather than a DSA key. If you try to use a DSA keypair (which I’m assuming is synonomous with Diffie-Hellman/DSS?), that I ran into:
org.bouncycastle.openpgp.PGPException: Can't use DSA for encryption, which again is explained by the link above.

Now that you downloaded the appropriate libraries, created an RSA keypair and located your public keyring file, we’re ready to start. Open up your favorite Java IDE (I’m using Eclipse) and start by importing the appropriate libraries:

import java.io.*;
import java.security.*;
import org.bouncycastle.bcpg.*;
import org.bouncycastle.jce.provider.*;
import org.bouncycastle.openpgp.*;

I took a shortcut above and didn’t specify exactly what classes I wanted to import for clarity, if you’re using Eclipse you can easily clean that up by selecting Source –> Organize Imports (or by downloading the source code at the end of this example). Next the class declaration and the standard public static void main etc.. The KeyBasedFileProcessor example on the BouncyCastle website lets you pass in the location of the public keyring and the file you want to encrypt, I’m hardcoding it in my code so that it’s crystal clear what everything is:

// the keyring that holds the public key we're encrypting with
String publicKeyFilePath = "C:\\pgp6.5.8\\pubring.pkr";

and then use the static addProvider() method of the java.security.Security class:

Security.addProvider(new BouncyCastleProvider());

Next I chose to create a temporary file to hold the message that I want to encrypt:

File outputfile = File.createTempFile("pgp", null);
FileWriter writer = new FileWriter(outputfile);
writer.write("the message I want to encrypt".toCharArray());
writer.close();

Read the public keyring file into a FileInputStream and then call the readPublicKey() method that was provided for us by the KeyBasedFileProcessor:

FileInputStream in = new FileInputStream(publicKeyFilePath);
PGPPublicKey key = readPublicKey(in);

At this point it’s important to note that the PGPPublicKeyRing class (at least in the version I was using) appears to have a bug where it only recognizes the first key in the keyring. If you use the getUserIds() method of the object returned you’ll only see one key:

for (java.util.Iterator iterator = key.getUserIDs(); iterator.hasNext();) {
System.out.println((String)iterator.next());
}

This could cause you problems if you have multiple keys in your keyring and if the first key is not an RSA or El Gamal key.

Finally, create an armored ASCII text file and call the encryptFile() method (again provided us by the KeyBasedFileProcessor example:

FileOutputStream out = new FileOutputStream(outputfile.getAbsolutePath() + ".asc");
// (file we want to encrypt, file to write encrypted text to, public key)
encryptFile(outputfile.getAbsolutePath(), out, key);

The rest of the example is almost verbatim from the KeyBaseFileProcessor example, I’ll paste the code here, but I didn’t do much to it:

out = new ArmoredOutputStream(out);
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedDataGenerator.ZIP);
PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
comData.close();
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(PGPEncryptedDataGenerator.CAST5, new SecureRandom(), "BC");
cPk.addMethod(encKey);
byte[] bytes = bOut.toByteArray();
OutputStream cOut = cPk.open(out, bytes.length);
cOut.write(bytes);
cPk.close();
out.close();

One last thing that I gleamed from their web-based forum was that one of the exceptions thrown by the above code is a PGPException, which itself doesn’t tell you much (in my case it was simply saying exception encrypting session key. PGPException can be a wrapper for an underlying exception though, and you should use the getUnderlyingException() method to determine what the real cause of the problem is (which lead me to the Can't use DSA for encryption message that I mentioned above).

You can download the source code and batch file for the example above here:

bouncy_castle_pgp_example.zip

Updated 04/07/2004: David Hook wrote to let me know that there is a bug in the examples, I updated both the sample code above and the zip file that contains the full source code. Look at the beta versions for the updated examples.

61 thoughts on “PGP Encryption using Bouncy Castle”

  1. I tried to encrypt a file using this. But it is giving a runtime error that is ‘passed in key not an encryption key’. Can u give me a solution

  2. I tried to encrypt a file using the beta 3 version with my client’s Public key. But it has given the following error. Can any one give some solution to this problem.
    org.bouncycastle.openpgp.PGPException: exception encrypting session key
    java.lang.SecurityException: Unsupported keysize or algorithm parameters
    at javax.crypto.Cipher.init(DashoA6275)
    at org.bouncycastle.openpgp.PGPEncryptedDataGenerator$PubMethod.addSessionInfo(PGPEncryptedDataGenerator.java:132)
    at org.bouncycastle.openpgp.PGPEncryptedDataGenerator.open(PGPEncryptedDataGenerator.java:340)
    at org.bouncycastle.openpgp.examples.KeyBasedFileProcessor.encryptFile(KeyBasedFileProcessor.java:256)
    at org.bouncycastle.openpgp.examples.KeyBasedFileProcessor.main(KeyBasedFileProcessor.java:304)

  3. >>This could cause you problems if you have multiple keys in your keyring and if the first key is not an RSA or El Gamal key.

    the readPublicKey() method in KeyBasedFileProcessor returns only the first (non-null) key. That is why there is a “problem” with multiple keys is a single ring.

    Modify that method to return a Collection of PGPPublicKeys and introduce some logic to pick the preferred key and your problem is solved.

    Thanks for a great tutorial
    – Ryan.

  4. I encrypted a big file using bouncycastle openpgp, but client can’t decrypting it with his private key. Can any one give me some solution for this problem to encrypt and decrypt large files using the bouncyCastle openpgp package.

    1. Hi Joshua, can you plz let me know how you encrypted the file. I am facing some error like can’t find the key from the publickey.asc file

  5. Works great when testing it in JBuilder but, when it make a jar file from my project, an error occure:
    >org.bouncycastle.openpgp.PGPException: exception encrypting session key
    >java.lang.SecurityException: The provider BC may not be signed by a trusted party

    After searching a solution, I found a similar bug on Sun’s dev forum :
    “do you use the signed jar from bouncycastle (BC) – if yes, just use the unsigned one”.
    Do you think it’s the solution?
    I’m a real newbie 🙂 What is a “unsigned jar” and how should I use it for this particular example?

  6. Hi…. I was getting the following exception when I was trying to run the “SignedFileProcessor” program in the examples.

    Can anyone pls advise me on this.

    ******************************
    Exception in thread “main” java.lang.UnsupportedClassVersionError: org/bouncyca
    tle/jce/provider/BouncyCastleProvider (Unsupported major.minor version 48.0)
    at java.lang.ClassLoader.defineClass0(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:703)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:1
    3)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:319)
    at java.net.URLClassLoader.access$400(URLClassLoader.java:92)
    at java.net.URLClassLoader$ClassFinder.run(URLClassLoader.java:677)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:238)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:516)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:441)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:448)
    *******************************

  7. Hi suresh….its looks like you are using the wrong version of “jar” files. Pls check your JVM version and use the respective “jar” file.

    -Seshu

  8. I encountered the following exception while running the “SignedFileProcessor” class.

    How do I resolve this ??

    *****************************
    Exception in thread “main” org.bouncycastle.openpgp.PGPException: Exception cons
    tructing key
    at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(PGPSecretKey.
    java:520)
    at SignedFileProcessor.signFile(SignedFileProcessor.java:57)
    at SignedFileProcessor.main(SignedFileProcessor.java:95)

    *****************************

  9. Thanks for the post, it was helpful. But just for everybody’s enlightenment: DSA is the digital signature algorithm. Since signatures are basically the opposite of public key encryption (everybody can read it, but only one person can write it) that’s why you couldn’t use a DSA keypair for encryption.

  10. Thanks Jay for the quick response…..could you pls suggest me which java file I need to use for Encryption of file using Public Key and UserID
    Decrypting the same with passphase.

    Thanking you in advance

  11. Hi
    I am having problems running the KeyBasedFileProcessor.
    It would be great if anyone could suggest me a solution.

    ******************************
    java org.bouncycastle.openpgp.examples.KeyBasedFileProcessor -e data.txt pubring.pkr

    Exception in thread “main” java.lang.NoSuchMethodError: java.lang.SecurityExcept
    ion: method initCause(Ljava/lang/Throwable;)Ljava/lang/Throwable; not found
    at javax.crypto.d.a(Unknown Source)
    at javax.crypto.d.a(Unknown Source)
    at javax.crypto.d.verify(Unknown Source)
    at javax.crypto.f.a(Unknown Source)
    at javax.crypto.f.(Unknown Source)
    at javax.crypto.Cipher.getInstance(Unknown Source)
    at org.bouncycastle.openpgp.PGPEncryptedDataGenerator$PubMethod.addSessi
    onInfo(PGPEncryptedDataGenerator.java:120)
    at org.bouncycastle.openpgp.PGPEncryptedDataGenerator.open(PGPEncryptedD
    ataGenerator.java:340)
    at org.bouncycastle.openpgp.examples.KeyBasedFileProcessor.encryptFile(K
    eyBasedFileProcessor.java:256)
    at org.bouncycastle.openpgp.examples.KeyBasedFileProcessor.main(KeyBased
    FileProcessor.java:304)
    *****************************

  12. Hi,
    Previously I was using bcpg-jdk14-123 and bcprov-jdk14-123. But our client asked me to use bcpg-jdk14-124 and bcprov-jdk14-124, so I downloaded this version and I am trying to encrypt some messages. But the problem is it is encrypting small files fine. But if I give big files the encrypted file size becomes very less regardless of the original file. We are unable to decrypt it also agian. But we want to encrypt files more than 1MB. It would be great if anyone could suggest me a solution.

    regards,
    Jashua

  13. I am using PGP Encryption

    Java Version : j2sdk1.4.1_06

    The policy files local_policy.jar US_export_policy.jar are placed in /lib/security folder.

    I am getting the following error

    java.lang.SecurityException: Unsupported keysize or algorithm parameters
    java.lang.SecurityException: Unsupported keysize or algorithm parameters
    at javax.crypto.Cipher.init(DashoA6275)
    at org.bouncycastle.openpgp.PGPEncryptedDataGenerator$PubMethod.addSessionInfo(PGPEncryptedDataGenerator.java:132)
    at org.bouncycastle.openpgp.PGPEncryptedDataGenerator.open(PGPEncryptedDataGenerator.java:340)

    Does any one give the solution for the above problem.

    Regards
    Pavan

  14. Hi,
    I am using bcpg-jdk14-124 and bcprov-jdk14-124 in my java application. The application works fine on Mac with DSA and ElGamal key. When I use the application on Windows with new keys(DSA and ElGamal), I get the following error:

    java.lang.SecurityException: Unsupported keysize or algorithm parameters
    at javax.crypto.Cipher.init(DashoA6275)
    at org.bouncycastle.openpgp.PGPEncryptedDataGenerator$PubMethod.addSessionInfo(PGPEncryptedDataGenerator.java:132)
    at org.bouncycastle.openpgp.PGPEncryptedDataGenerator.open(PGPEncryptedDataGenerator.java:340)

    Then I generated my key with RSA. Now I am able to encrypt my message. But it doesn’t end here, now the decryption doesn’t work. I do not get any exception. Can anyone help me out of this? I am using the following method(please look for the FIXME in the code snippet)

    /////////////////////////////////////////////////////////////////////////////

    public byte[] decryptedBytes(byte[] encryptedBytes, String recipientPassPhrase) throws GeneralSecurityException
    {
    byte[] decryptedBytes = null;

    try
    {
    char[] passPhraseArray = (recipientPassPhrase == null) ? BCPGPCrypto.EmptyCharArray : recipientPassPhrase.toCharArray();

    InputStream sourceStream = PGPUtil.getDecoderStream(new ByteArrayInputStream(encryptedBytes));

    PGPObjectFactory pgpFactory = new PGPObjectFactory(sourceStream);
    PGPEncryptedDataList encDataList;

    Object o = pgpFactory.nextObject();
    //
    // the first object might be a PGP marker packet.
    //
    if (o instanceof PGPEncryptedDataList)
    {
    encDataList = (PGPEncryptedDataList) o;
    }
    else
    {
    encDataList = (PGPEncryptedDataList) pgpFactory.nextObject();
    }

    PGPPublicKeyEncryptedData encryptedData = (PGPPublicKeyEncryptedData) encDataList.get(0);

    PGPPrivateKey privateKey = findSecretKey(encryptedData.getKeyID(), passPhraseArray);

    InputStream clear = null;

    try{

    clear = encryptedData.getDataStream(privateKey, “BC”);

    }catch(Exception e){
    e.printStackTrace();
    }

    PGPObjectFactory plainFact = new PGPObjectFactory(clear);

    PGPCompressedData compressedData = (PGPCompressedData) plainFact.nextObject();

    PGPObjectFactory pgpFact = new PGPObjectFactory(compressedData.getDataStream());

    Object message = pgpFact.nextObject();

    ByteArrayOutputStream decryptedStream = new ByteArrayOutputStream();

    if (message instanceof PGPLiteralData)
    {
    PGPLiteralData literalData = (PGPLiteralData) message;

    InputStream unc = literalData.getInputStream();

    int ch;

    //FIXME
    //On windows the control does not enter inside this loop
    while ((ch = unc.read()) >= 0)
    {
    decryptedStream.write(ch);
    }

    }

    decryptedStream.flush();

    decryptedBytes = decryptedStream.toByteArray();

    }
    catch (IOException e)
    {
    GeneralSecurityException e1 = new GeneralSecurityException(“There was a problem while reading from/writing to a stream : ” + e.toString());
    e1.initCause(e);
    throw e1;
    }
    catch (PGPException e)
    {
    e.getUnderlyingException().printStackTrace();
    GeneralSecurityException e1 = new GeneralSecurityException(“Wrapping BouncyCastle(OpenPGP) generic exception :” + e.toString());
    e1.initCause(e);
    throw e1;
    }

    return decryptedBytes;

    }

    /////////////////////////////////////////////////////////////////////////////

  15. I tried to encrypt a file.I am getting following exception

    org.bouncycastle.openpgp.PGPException: Exception creating cipher

    java.lang.IllegalArgumentException: can’t support mode OpenPGPCFB

  16. hi,
    i was able to encrypt a file using the bouncy castle class PGPEncryptedDataGenerator. does someone here know which class to start with for decryption?

    thanks,

  17. Hello,
    I’m having problems decrypting a signed message. I first created a class that’s a variation of the KeyBasedFileProcessor. I’m able to decrypt unsigned messages fine but with signed messages, I got- “org.bouncycastle.openpgp.PGPException: encrypted message contains a signed message – not literal data..”…

    Sooo… I concluded I probably need to use the SignedFileProcessor example to decrypt signed messages. Now, when I attempt to decrypt, I get a ClassCastException at the following line-

    PGPCompressedData c1 = (PGPCompressedData)pgpFact.nextObject();

    Has anyone run into this or have suggestions? I’m stuck.
    Thank You,
    -Bob

  18. Hello, Any one has answer for this question?

    I encrypted a big file using bouncycastle openpgp, but client can’t decrypting it with his private key. Can any one give me some solution for this problem to encrypt and decrypt large files using the bouncyCastle openpgp package.

  19. this is wrong
    FileOutputStream out = new FileOutputStream(outputfile.getAbsolutePath() + “.asc”);
    it should be
    OutputStream out = new FileOutputStream(outputfile.getAbsolutePath() + “.asc”);

  20. If you’re getting the error:
    java.lang.SecurityException: Unsupported keysize or algorithm parameters
    at javax.crypto.Cipher.init(DashoA6275)

    You need to download and install the JCE Unlimited Strength Jurisdiction Policy Files. You can find the download where the jdk download is.

    -Gene

  21. Gene
    I downloaded the policy files but still not able to resolve the error it still says
    org.bouncycastle.openpgp.PGPException: Exception decrypting key
    java.lang.SecurityException: Unsupported keysize or algorithm parameters
    at javax.crypto.Cipher.init(ILjava.security.Key;Ljava.security.spec.AlgorithmParameterSpec;)V(DashoA6275:???)

    I’m using Bouncy castle api for decryption..but get the above error..

    Thanks in advance

  22. Found the real cause..wasn’t properly placing the policy files..the should be placed in /jre/lib/security under the java 1.4 installation directory..
    Thanks all

  23. I just find your article. (2 years later)
    I’m interested in use of Bouncy castle pour PGP encryption.
    I see in your post that we should first use PGP to create the public/private keyring file.
    In fact, i’d like to do a little application entirely in Java and store if possible the public key in PKS (should be an openLDAP server configured with the pgp-key schema)

    This application should be distributed to end users who don’t know anything about encryption, and couldn’t use PGP to first create the keyring files.

    How can i do a solution in Java from A to Z.
    If you have an idea. Thanks

  24. I’d been having trouble with decrypting signed and/or zipped files, and googling for quick examples didn’t turn up much, so I figured I’d share my solutions here. It seems other people here have asked about these types of files.

    My code is based on Aaron Johnson’s example.

    code snippet:

    try {
    InputStream in = new FileInputStream(encryptedFile);
    InputStream keyIn = new FileInputStream(privateKeyFilePath);
    BufferedOutputStream bOut = null;

    char[] passwd = privateKeyPass.toCharArray();

    in = PGPUtil.getDecoderStream(in);

    PGPObjectFactory pgpF = new PGPObjectFactory(in);
    PGPEncryptedDataList enc;
    Object o = pgpF.nextObject();

    //
    // the first object might be a PGP marker packet.
    //
    if (o instanceof PGPEncryptedDataList)
    {
    enc = (PGPEncryptedDataList)o;
    }
    else
    {
    enc = (PGPEncryptedDataList)pgpF.nextObject();
    }

    //
    // find the secret key
    //
    Iterator it = enc.getEncryptedDataObjects();
    PGPPrivateKey sKey = null;
    PGPPublicKeyEncryptedData pbe = null;

    while (sKey == null && it.hasNext())
    {
    pbe = (PGPPublicKeyEncryptedData)it.next();

    sKey = findSecretKey(keyIn, pbe.getKeyID(), passwd);
    }

    if (sKey == null) // can’t find secret key
    {
    in.close();
    keyIn.close();
    return;
    }

    InputStream clear = pbe.getDataStream(sKey, “BC”);

    PGPObjectFactory plainFact = new PGPObjectFactory(clear);

    Object thing = plainFact.nextObject();
    Object message = null;

    if (thing instanceof PGPLiteralData) {

    message = thing;

    } else if (thing instanceof PGPCompressedData) {
    //
    // file is zipped!
    //

    PGPCompressedData cData = (PGPCompressedData) thing;

    InputStream compressedStream = new BufferedInputStream(cData.getDataStream());
    PGPObjectFactory pgpFact = new PGPObjectFactory(compressedStream);

    message = pgpFact.nextObject();

    if (message instanceof PGPOnePassSignatureList) {
    //
    // file is signed!
    //

    // verify signature here if you want.
    //
    // PGPOnePassSignatureList p1 = (PGPOnePassSignatureList) message;
    // PGPOnePassSignature ops = p1.get(0);
    // etc…

    message = pgpFact.nextObject();
    }
    }

    if (message instanceof PGPLiteralData)
    {
    //
    // decrypt as normal
    //
    }
    else
    {
    retval = “message type ” + message.toString() + ” not supported.”;
    }
    if (pbe.isIntegrityProtected())
    {
    if (!pbe.verify())
    {
    retval = “message failed integrity check”;
    }
    }

    bOut.close();
    in.close();
    keyIn.close();

    } catch (PGPException pgpe) {
    //
    // etc…..

    Thanks to David Hook for his suggestion to me in the Bouncycastle mailing list.

    -Jack

  25. Hi,

    I was just wondering if using Bouncy Castle (to be more specific using this example) is governed by US export restrictions.

    regards,
    Dipak

  26. When using gpg to create my keys, options 1 (DSA and Elgamal) and 2 (DSA (sign only)) doesn’t work. I get “java.lang.IllegalArgumentException: passed in key not an encryption key!” from cPk.addMethod(encKey);

    When I use gpg’s option 5 (RSA (sign only)), I am able to successfully encrypt and decrypt. This happens regardless of gpg’s claim: “Note that this key cannot be used for encryption. You may want to use
    the command “–edit-key” to generate a subkey for this purpose.”

    According to the recipe above, an Elgamal should have worked?

    Have anyone managed to get bouncycastle to work with regular (DSA and Elgamal) gpg keys?

  27. I got the default gpg key to work anyway, as I discovered that the encryption key (Elgamal) is a subkey of the main (signing, DSA) key. (“gpg –list-keys” was useful.)

    By iterating over the keys (pgpPub.getPublicKeys()), I discovered that the second key was the encryption key (pk.isEncryptionKey()).

    Voila! It really happens too often that I solve a problem by formulating it properly in a comment or post 🙂

    1. I tried the same thing, but getting the error as “org.bouncycastle.openpgp.PGPException: exception encrypting session key”, did u ever encounter this type of error ? really appreciate if anbody can help me on this.

  28. I need to knw how to do decryption after using the above code for encryption – I am not able to use PGPLiteral data – can anyone help me with snippet for readin .asc file and private key and get me literal data

  29. Hi guys,
    Actually I’m new cyrptography.
    I need to clarify few doubts..
    1> Can we use Boucy castle to implement PGP for encryption / decryption.?
    2> Can we generate PGP keys using bouoncy castle.? and How..?

    Please help me to find this out as I have my deliverable wating.!

    Thankx in advance,
    Sirish.

  30. Thanks for sharing this code! I have a question though – When you call the [encryptFile(outputfile.getAbsolutePath(), out, key);] method – it appears that the outputfile that is being referred to is the temp file that was previous created which in turn holds: “the message I want to encrypt”. How do you actually encrypt a ‘real’ file that is about ~800 kb big?
    Thanks!

  31. We are using IBM JVM ( java full version “J2RE 1.4.2 IBM AIX 5L for PowerPC (64 bit JVM) build caix64142ifx-20061222 (ifix 113727: SR7 + 112603)”. We are getting java.lang.runtime Unspported Version:1 error. Please advice if it works on IBM JVM?

  32. Hi Sabrina.

    This is from the example:

    File outputfile = File.createTempFile(“pgp”, null);
    FileWriter writer = new FileWriter(outputfile);
    writer.write(“the message I want to encrypt”.toCharArray());
    writer.close();

    Delete this stuff and just write:

    File outputfile = new File(HERE YOU WRITE THE PATH TO THE FILE);

    Example:

    File outputfile = new File(
    /home/xxxxx/movie.m2t)

    Should work then.
    Hope this helps.

    Greetings

  33. Hi Sabrina.
    This is from the example:

    File outputfile = File.createTempFile(“pgp”, null);
    FileWriter writer = new FileWriter(outputfile);
    writer.write(“the message I want to encrypt”.toCharArray());
    writer.close();

    Delete it and just write something like this:

    File outputfile = new File(“HERE THE PATH OF THE FILE”);

  34. when I run test.java that came along with bckprov jar am getting following exception

    Creating a temp file…
    Temp file created at
    c:\pgptest.txt
    Reading the temp file to make sure that the bits were written
    —————————-
    testng PGP again I want to encrypt

    in key functionorg.bouncycastle.openpgp.PGPPublicKey@1c1ea29
    Got keyorg.bouncycastle.openpgp.PGPPublicKey@1c1ea29
    Key Strength = 2048
    Algorithm = 1
    Pardha Saradhy Venkata Sathya Nallanthighal
    Key Count = 1
    creating comData…
    comData created…
    using PGPEncryptedDataGenerator…
    used PGPEncryptedDataGenerator…
    Bytes:[B@df503
    wrote bOut to byte array…
    org.bouncycastle.openpgp.PGPException: exception encrypting session key
    java.lang.SecurityException: The provider BC may not be signed by a trusted party

    Can any body please help me in solving this?

  35. Hello all,

    How can I use a asc File beginning with
    “—–BEGIN PGP PUBLIC KEY BLOCK—–”

    to encrypt the file. I don’t have a keyring and can’t extract one with WinPT.

    Thanks,
    John

  36. Hi,

    Can you please tell me how to decrypt the above example using java.

    Sample code will be appreciated

    Thanks
    Aman

  37. Hi,

    I need one XML file and I need to encryppt the message. Could uou please share steps and code for that logic?

  38. hi can anyone give me the code to generate pgp public key,private key and passphrase using bouncy castle.

  39. I am using latest version of jars from bcPgp.
    but we created the keys usinjg the old version fo PGP 6.5 software.Still I am able to encrypt but unable to decrypt.
    I am getting the below exception:
    org.bouncycastle.openpgp.PGPException: Exception creating cipher
    java.security.NoSuchAlgorithmException: No such algorithm: IDEA/CFB/NoPadding
    at javax.crypto.Cipher.getInstance(DashoA13*..)
    at javax.crypto.Cipher.getInstance(DashoA13*..)
    at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(PGPSecretKey.java:389)
    at org.bouncycastle.openpgp.examples.KeyBasedFileProcessor.findSecretKey(KeyBasedFileProcessor.java:132)
    at org.bouncycastle.openpgp.examples.KeyBasedFileProcessor.decryptFile(KeyBasedFileProcessor.java:166)
    at org.bouncycastle.openpgp.examples.KeyBasedFileProcessor.main(KeyBasedFileProcessor.java:311)

  40. I’ve gotten your example working. I only need some encrypted text, not encrypted files. Any suggestions on how to accomplish this?

    thanks

  41. It’s really easy start up for the beginners. Thank you Bouncy!

    Do you have API support for encrypting a zip file?

  42. Does Bouncy Castle supports DSA ? I have generated the key using options 1 (DSA and Elgamal) and 2 (DSA (sign only)), when i tried to encrypt using these keys endup with the error “passed in key not an encryption key”.

  43. This is a modified version to support multiple public keys resolving the bug you mentioned in your note.

    package org.bouncycastle.openpgp;

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;

    import org.bouncycastle.bcpg.BCPGInputStream;
    import org.bouncycastle.bcpg.PacketTags;
    import org.bouncycastle.bcpg.PublicKeyPacket;
    import org.bouncycastle.bcpg.TrustPacket;

    /**
    * Class to hold a single master public key and its subkeys.
    *
    * Often PGP keyring files consist of multiple master keys, if you are trying to process
    * or construct one of these you should use the PGPPublicKeyRingCollection class.
    */
    public class PGPPublicKeyRing
    extends PGPKeyRing
    {
    List keys;

    public PGPPublicKeyRing(
    byte[] encoding)
    throws IOException
    {
    this(new ByteArrayInputStream(encoding));
    }

    /**
    * @param pubKeys
    */
    PGPPublicKeyRing(
    List pubKeys)
    {
    this.keys = pubKeys;
    }

    public PGPPublicKeyRing(
    InputStream in)
    throws IOException
    {
    keys = new ArrayList();

    BCPGInputStream pIn = wrap(in);

    readPublicKeys( pIn, keys );
    }

    private void readPublicKeys( BCPGInputStream pIn, List keys) throws IOException {

    int initialTag = pIn.nextPacketTag();
    if (initialTag != PacketTags.PUBLIC_KEY && initialTag != PacketTags.PUBLIC_SUBKEY)
    {
    throw new IOException(
    “public key ring doesn’t start with public key tag: ” +
    “tag 0x” + Integer.toHexString(initialTag));
    }

    PublicKeyPacket pubPk = (PublicKeyPacket)pIn.readPacket();
    TrustPacket trustPk = readOptionalTrustPacket(pIn);

    // direct signatures and revocations
    List keySigs = readSignaturesAndTrust(pIn);

    List ids = new ArrayList();
    List idTrusts = new ArrayList();
    List idSigs = new ArrayList();
    readUserIDs(pIn, ids, idTrusts, idSigs);

    keys.add(new PGPPublicKey(pubPk, trustPk, keySigs, ids, idTrusts, idSigs));

    int nextTag = pIn.nextPacketTag();
    // Read subkeys
    while ( nextTag == PacketTags.PUBLIC_SUBKEY)
    {
    keys.add(readSubkey(pIn));
    }

    if( nextTag == PacketTags.PUBLIC_KEY){
    readPublicKeys( pIn, keys );
    }
    }

    /**
    * Return the first public key in the ring.
    *
    * @return PGPPublicKey
    */
    public PGPPublicKey getPublicKey()
    {
    return (PGPPublicKey)keys.get(0);
    }

    /**
    * Return the public key referred to by the passed in keyID if it
    * is present.
    *
    * @param keyID
    * @return PGPPublicKey
    */
    public PGPPublicKey getPublicKey(
    long keyID)
    {
    for (int i = 0; i != keys.size(); i++)
    {
    PGPPublicKey k = (PGPPublicKey)keys.get(i);

    if (keyID == k.getKeyID())
    {
    return k;
    }
    }

    return null;
    }

    /**
    * Return an iterator containing all the public keys.
    *
    * @return Iterator
    */
    public Iterator getPublicKeys()
    {
    return Collections.unmodifiableList(keys).iterator();
    }

    public byte[] getEncoded()
    throws IOException
    {
    ByteArrayOutputStream bOut = new ByteArrayOutputStream();

    this.encode(bOut);

    return bOut.toByteArray();
    }

    public void encode(
    OutputStream outStream)
    throws IOException
    {
    for (int i = 0; i != keys.size(); i++)
    {
    PGPPublicKey k = (PGPPublicKey)keys.get(i);

    k.encode(outStream);
    }
    }

    /**
    * Returns a new key ring with the public key passed in
    * either added or replacing an existing one.
    *
    * @param pubRing the public key ring to be modified
    * @param pubKey the public key to be inserted.
    * @return a new keyRing
    */
    public static PGPPublicKeyRing insertPublicKey(
    PGPPublicKeyRing pubRing,
    PGPPublicKey pubKey)
    {
    List keys = new ArrayList(pubRing.keys);
    boolean found = false;
    boolean masterFound = false;

    for (int i = 0; i != keys.size();i++)
    {
    PGPPublicKey key = (PGPPublicKey)keys.get(i);

    if (key.getKeyID() == pubKey.getKeyID())
    {
    found = true;
    keys.set(i, pubKey);
    }
    if (key.isMasterKey())
    {
    masterFound = true;
    }
    }

    if (!found)
    {
    if (pubKey.isMasterKey())
    {
    if (masterFound)
    {
    throw new IllegalArgumentException(“cannot add a master key to a ring that already has one”);
    }

    keys.add(0, pubKey);
    }
    else
    {
    keys.add(pubKey);
    }
    }

    return new PGPPublicKeyRing(keys);
    }

    /**
    * Returns a new key ring with the public key passed in
    * removed from the key ring.
    *
    * @param pubRing the public key ring to be modified
    * @param pubKey the public key to be removed.
    * @return a new keyRing, null if pubKey is not found.
    */
    public static PGPPublicKeyRing removePublicKey(
    PGPPublicKeyRing pubRing,
    PGPPublicKey pubKey)
    {
    List keys = new ArrayList(pubRing.keys);
    boolean found = false;

    for (int i = 0; i < keys.size();i++)
    {
    PGPPublicKey key = (PGPPublicKey)keys.get(i);

    if (key.getKeyID() == pubKey.getKeyID())
    {
    found = true;
    keys.remove(i);
    }
    }

    if (!found)
    {
    return null;
    }

    return new PGPPublicKeyRing(keys);
    }

    static PGPPublicKey readSubkey(BCPGInputStream in)
    throws IOException
    {
    PublicKeyPacket pk = (PublicKeyPacket)in.readPacket();
    TrustPacket kTrust = readOptionalTrustPacket(in);

    // PGP 8 actually leaves out the signature.
    List sigList = readSignaturesAndTrust(in);

    return new PGPPublicKey(pk, kTrust, sigList);
    }
    }

  44. Reviewing the code I saw that the correct way to get all public keys inside the keyring is using the class PGPPublicKeyRingCollection.

  45. Hi Experts,

    While encrypting the input message using public key we are getting the below error exception .
    ” java.security.NoSuchAlgorithmException: No such algorithm: RSA/ECB/PKCS1Padding” .

    Here is the small piece of code we used for encryption .

    inKey = PGPUtil.getDecoderStream(inKey); // inKey contains public key info
    PGPPublicKeyRingCollection pkCol = new PGPPublicKeyRingCollection(inKey);
    Iterator it = pkCol.getKeyRings();
    while (it.hasNext()) {pkRing = (PGPPublicKeyRing) it.next();
    Iterator pkIt = pkRing.getPublicKeys();
    while (pkIt.hasNext()) {
    temp = (PGPPublicKey) pkIt.next();
    if (temp.isEncryptionKey()) {
    pubkey = temp;
    break; } }

    out = new DataOutputStream(out);
    ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedDataGenerator.ZIP);
    PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();
    OutputStream pOut = lData.open(comData.open(bOut),PGPLiteralData.BINARY, “”, inputString.length(),new Date());
    pOut.write(inputString.getBytes());
    lData.close();
    comData.close();
    cPk.close(); out.close();
    PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(PGPEncryptedDataGenerator.CAST5, new SecureRandom(),”BC”);
    cPk.addMethod(pubkey);
    byte[] bytes = bOut.toByteArray();
    OutputStream cOut = cPk.open(out, bytes.length); //<– Here we are getting the above exception
    cOut.write(bytes);
    cPk.close();
    out.close();

    Could any one plz guide us ???

  46. You got

    org.bouncycastle.openpgp.PGPException: Can’t use DSA for encryption

    because DSA is Digital Signature Algorithm which is used for file signing not for encryption.

  47. I am trying to encrypt a text file by using public key and bouncy castle algorithm. I am getting the below error:
    org.bouncycastle.openpgp.PGPException: exception constructing public key

    I had also changed the security files in jre of the application server – Tomcat. But still i am getting this issue. Below is the piece of code i am using for encryption:

    private static void _encrypt(String fileName, OutputStream out, PGPPublicKey encKey)
    throws IOException, NoSuchProviderException, PGPException, NoSuchPaddingException
    {
    out = new DataOutputStream(out);
    ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    System.out.println(“creating comData…”);

    // get the data from the original file
    PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedDataGenerator.ZIP);
    PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
    comData.close();
    System.out.println(“comData created…”);
    System.out.println(“using PGPEncryptedDataGenerator…”);

    // object that encrypts the data
    PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(PGPEncryptedDataGenerator.CAST5,
    new SecureRandom(), “BC”);
    cPk.addMethod(encKey);
    System.out.println(“used PGPEncryptedDataGenerator…”);

    // take the outputstream of the original file and turn it into a byte array
    byte[] bytes = bOut.toByteArray();
    System.out.println(“wrote bOut to byte array…”);

    // write the plain text bytes to the armored outputstream

    OutputStream cOut = cPk.open(out, bytes.length);
    cOut.write(bytes);
    cPk.close();
    out.close();
    }

  48. I am using bouncy castle PGP software to do encrypton and decryption. The solution is working fine now. We got new request from 1 of the customer that, They are encrypting the data and then doing the signing of the message.

    Will Bouncy castle support decryption and then verifying the signing message. If so, Please share the link/code for implementing in Java.

  49. i am able to encrypt a csv file not able to decrypt a csv file by using secring.skr key. I am getting the below error:can please help to reslove this issue.
    Exception in thread “main” java.lang.IllegalArgumentException: Secret key for message not found.
    at custom.pgp.CSPGPUtil.decryptFile(CSPGPUtil.java:159)
    at custom.pgp.PGPFileProcessor.decrypt(PGPFileProcessor.java:33)
    at custom.pgp.PGPTestDe.main(PGPTestDe.java:36)

  50. I am using the .Net C# solution for Bouncy castle. I was able to create private and public keys in ascii armor format. A client enrypted a file for us using our public pgp key and sent us the file which has .asc file ext.

    When I call the Decryption method the code throws a casting exception which I noted about 3/4 down in the code block. Any ideas would be appreciated. The exception is:

    Unable to cast object of type ‘Org.BouncyCastle.Bcpg.OpenPgp.PgpOnePassSignatureList’ to type ‘Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedData’.

    The code block that I am using from the BC KeyBasedFileProcessor class:

    using System;
    using System.Collections;
    using System.IO;
    using Org.BouncyCastle.Bcpg.OpenPgp;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.Utilities.IO;

    namespace ConsoleApplication2008
    {
    public class BC
    {
    public void DecryptFile(string inputFileNamePath,
    string keyFileNamePath,
    char[] passwd,
    string OutputFileNamepath)
    {
    using (Stream input = File.OpenRead(inputFileNamePath),
    keyIn = File.OpenRead(keyFileNamePath))
    {
    DecryptFile(input, keyIn, passwd, OutputFileNamepath);
    }
    }

    public static void DecryptFile(
    Stream inputStream,
    Stream keyIn,
    char[] passwd,
    string defaultFileName)
    {
    inputStream = PgpUtilities.GetDecoderStream(inputStream);

    try
    {
    PgpObjectFactory pgpF = new PgpObjectFactory(inputStream);
    PgpEncryptedDataList enc;

    PgpObject o = pgpF.NextPgpObject();
    //
    // the first object might be a PGP marker packet.
    //
    if (o is PgpEncryptedDataList)
    {
    enc = (PgpEncryptedDataList)o;
    }
    else
    {
    enc = (PgpEncryptedDataList)pgpF.NextPgpObject();
    }

    //
    // find the secret key
    //
    PgpPrivateKey sKey = null;
    PgpPublicKeyEncryptedData pbe = null;
    PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(keyIn));

    foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects())
    {
    sKey = BCUtility.FindSecretKey(pgpSec, pked.KeyId, passwd);

    if (sKey != null)
    {
    pbe = pked;
    break;
    }
    }

    if (sKey == null)
    {
    throw new ArgumentException(“secret key for message not found.”);
    }

    Stream clear = pbe.GetDataStream(sKey);

    PgpObjectFactory plainFact = new PgpObjectFactory(clear);
    //****Error occurs at the next line where is cast is made.******
    PgpCompressedData cData = (PgpCompressedData)plainFact.NextPgpObject();

    PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream());

    PgpObject message = pgpFact.NextPgpObject();

    if (message is PgpLiteralData)
    {
    PgpLiteralData ld = (PgpLiteralData)message;

    string outFileName = ld.FileName;
    if (outFileName.Length == 0)
    {
    outFileName = defaultFileName;
    }

    Stream fOut = File.Create(outFileName);
    Stream unc = ld.GetInputStream();
    Streams.PipeAll(unc, fOut);
    fOut.Close();
    }
    else if (message is PgpOnePassSignatureList)
    {
    throw new PgpException(“encrypted message contains a signed message – not literal data.”);
    }
    else
    {
    throw new PgpException(“message is not a simple encrypted file – type unknown.”);
    }

    if (pbe.IsIntegrityProtected())
    {
    if (!pbe.Verify())
    {
    Console.Error.WriteLine(“message failed integrity check”);
    }
    else
    {
    Console.Error.WriteLine(“message integrity check passed”);
    }
    }
    else
    {
    Console.Error.WriteLine(“no message integrity check”);
    }
    }
    catch (PgpException e)
    {
    Console.Error.WriteLine(e);

    Exception underlyingException = e.InnerException;
    if (underlyingException != null)
    {
    Console.Error.WriteLine(underlyingException.Message);
    Console.Error.WriteLine(underlyingException.StackTrace);
    }
    }
    }
    }
    }

Leave a Reply to Suresh Cancel reply

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