title: Encrypt/Decrypt Files Using Bouncy Castle PGP in JAVA
body: <p>I am generating Keypair for PGP Encryption using this class and saving the Files to the disk.</p>
  
  <pre><code>import java.io.BufferedOutputStream;
  import java.io.FileOutputStream;
  import java.math.BigInteger;
  import java.security.SecureRandom;
  import java.util.Date;
  
  import org.bouncycastle.bcpg.ArmoredOutputStream;
  import org.bouncycastle.bcpg.HashAlgorithmTags;
  import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
  import org.bouncycastle.bcpg.sig.Features;
  import org.bouncycastle.bcpg.sig.KeyFlags;
  import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
  import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
  import org.bouncycastle.openpgp.PGPEncryptedData;
  import org.bouncycastle.openpgp.PGPKeyPair;
  import org.bouncycastle.openpgp.PGPPublicKeyRing;
  import org.bouncycastle.openpgp.PGPKeyRingGenerator;
  import org.bouncycastle.openpgp.PGPPublicKey;
  import org.bouncycastle.openpgp.PGPSecretKeyRing;
  import org.bouncycastle.openpgp.PGPSignature;
  import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
  import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
  import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
  import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyEncryptorBuilder;
  import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
  import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
  import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair;
  
  public class RSAGen {
      public static void Generate(String ID,String PassPhrase , String FileName) throws Exception {
          char pass[] = PassPhrase.toCharArray();
          PGPKeyRingGenerator krgen = generateKeyRingGenerator(ID, pass);
  
          // Generate public key ring, dump to file.
          PGPPublicKeyRing pkr = krgen.generatePublicKeyRing();
          ArmoredOutputStream pubout = new ArmoredOutputStream(new BufferedOutputStream(new FileOutputStream(FileName + ".asc")));
          pkr.encode(pubout);
          pubout.close();
  
          // Generate private key, dump to file.
          PGPSecretKeyRing skr = krgen.generateSecretKeyRing();
          BufferedOutputStream secout = new BufferedOutputStream(new FileOutputStream(FileName + ".skr"));
          skr.encode(secout);
          secout.close();
      }
  
      public final static PGPKeyRingGenerator generateKeyRingGenerator(String id, char[] pass) throws Exception{
          return generateKeyRingGenerator(id, pass, 0xc0);
      }
  
      // Note: s2kcount is a number between 0 and 0xff that controls the number of times to iterate the password hash before use. More
      // iterations are useful against offline attacks, as it takes more time to check each password. The actual number of iterations is
      // rather complex, and also depends on the hash function in use. Refer to Section 3.7.1.3 in rfc4880.txt. Bigger numbers give
      // you more iterations.  As a rough rule of thumb, when using SHA256 as the hashing function, 0x10 gives you about 64
      // iterations, 0x20 about 128, 0x30 about 256 and so on till 0xf0, or about 1 million iterations. The maximum you can go to is
      // 0xff, or about 2 million iterations.  I'll use 0xc0 as a default -- about 130,000 iterations.
  
      public final static PGPKeyRingGenerator generateKeyRingGenerator(String id, char[] pass, int s2kcount) throws Exception {
          // This object generates individual key-pairs.
          RSAKeyPairGenerator  kpg = new RSAKeyPairGenerator();
  
          // Boilerplate RSA parameters, no need to change anything
          // except for the RSA key-size (2048). You can use whatever key-size makes sense for you -- 4096, etc.
          kpg.init(new RSAKeyGenerationParameters(BigInteger.valueOf(0x10001), new SecureRandom(), 2048, 12));
  
          // First create the master (signing) key with the generator.
          PGPKeyPair rsakp_sign = new BcPGPKeyPair(PGPPublicKey.RSA_SIGN, kpg.generateKeyPair(), new Date());
          // Then an encryption subkey.
          PGPKeyPair rsakp_enc = new BcPGPKeyPair(PGPPublicKey.RSA_ENCRYPT, kpg.generateKeyPair(), new Date());
  
          // Add a self-signature on the id
          PGPSignatureSubpacketGenerator signhashgen = new PGPSignatureSubpacketGenerator();
  
          // Add signed metadata on the signature.
          // 1) Declare its purpose
          signhashgen.setKeyFlags(false, KeyFlags.SIGN_DATA|KeyFlags.CERTIFY_OTHER);
          // 2) Set preferences for secondary crypto algorithms to use when sending messages to this key.
          signhashgen.setPreferredSymmetricAlgorithms
                  (false, new int[] {
                          SymmetricKeyAlgorithmTags.AES_256,
                          SymmetricKeyAlgorithmTags.AES_192,
                          SymmetricKeyAlgorithmTags.AES_128
                  });
          signhashgen.setPreferredHashAlgorithms
                  (false, new int[] {
                          HashAlgorithmTags.SHA256,
                          HashAlgorithmTags.SHA1,
                          HashAlgorithmTags.SHA384,
                          HashAlgorithmTags.SHA512,
                          HashAlgorithmTags.SHA224,
                  });
          // 3) Request senders add additional checksums to the message (useful when verifying unsigned messages.)
          signhashgen.setFeature(false, Features.FEATURE_MODIFICATION_DETECTION);
  
          // Create a signature on the encryption subkey.
          PGPSignatureSubpacketGenerator enchashgen = new PGPSignatureSubpacketGenerator();
          // Add metadata to declare its purpose
          enchashgen.setKeyFlags(false, KeyFlags.ENCRYPT_COMMS|KeyFlags.ENCRYPT_STORAGE);
  
          // Objects used to encrypt the secret key.
          PGPDigestCalculator sha1Calc = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA1);
          PGPDigestCalculator sha256Calc = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA256);
  
          // bcpg 1.48 exposes this API that includes s2kcount. Earlier versions use a default of 0x60.
          PBESecretKeyEncryptor pske = (new BcPBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, sha256Calc, s2kcount)).build(pass);
  
          // Finally, create the keyring itself. The constructor takes parameters that allow it to generate the self signature.
          PGPKeyRingGenerator keyRingGen =
                  new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, rsakp_sign,
                          id, sha1Calc, signhashgen.generate(), null,
                          new BcPGPContentSignerBuilder(rsakp_sign.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1), pske);
  
          // Add our encryption subkey, together with its signature.
          keyRingGen.addSubKey(rsakp_enc, enchashgen.generate(), null);
          return keyRingGen;
      }
  }
  </code></pre>
  
  <p>i found this class but it won't work with the latest version which is :
  -bcpg-jdk15on-1.54
  -bcprov-jdk15on-1.54</p>
  
  <p>i got lot's of error message when using this class :
  <a href="https://github.com/matthewmccullough/encryption-jvm-bootcamp/blob/master/bc-pgp/src/main/java/com/ambientideas/cryptography/KeyBasedFileProcessorUtil.java" rel="nofollow">https://github.com/matthewmccullough/encryption-jvm-bootcamp/blob/master/bc-pgp/src/main/java/com/ambientideas/cryptography/KeyBasedFileProcessorUtil.java</a></p>
  
  <pre><code>package com.ambientideas.cryptography;
  
  import org.bouncycastle.bcpg.ArmoredOutputStream;
  import org.bouncycastle.jce.provider.BouncyCastleProvider;
  import org.bouncycastle.openpgp.PGPCompressedData;
  import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
  import org.bouncycastle.openpgp.PGPEncryptedData;
  import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;
  import org.bouncycastle.openpgp.PGPEncryptedDataList;
  import org.bouncycastle.openpgp.PGPException;
  import org.bouncycastle.openpgp.PGPLiteralData;
  import org.bouncycastle.openpgp.PGPObjectFactory;
  import org.bouncycastle.openpgp.PGPOnePassSignatureList;
  import org.bouncycastle.openpgp.PGPPrivateKey;
  import org.bouncycastle.openpgp.PGPPublicKey;
  import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
  import org.bouncycastle.openpgp.PGPPublicKeyRing;
  import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
  import org.bouncycastle.openpgp.PGPSecretKey;
  import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
  import org.bouncycastle.openpgp.PGPUtil;
  
  import java.io.ByteArrayOutputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.security.NoSuchProviderException;
  import java.security.SecureRandom;
  import java.security.Security;
  import java.util.Iterator;
  
  //Matthew McCullough: Rediculous as it sounds, many of the functions such as 
  // private static void encryptFile()
  // private static void decryptFile()
  // private static PGPPrivateKey findSecretKey()
  // private static PGPPublicKey readPublicKey()
  // for PGP in BouncyCastle are private, thus making it unbearable to use
  // in a simple manner against whole file contents. Thus, this class is duplicated from the
  // core of BouncyCastle (KeyBasedFileProcessor being the original name), but with the
  // methods made public so that the test can use them.
  
  /**
   * A simple utility class that encrypts/decrypts public key based
   * encryption files.
   * &lt;p&gt;
   * To encrypt a file: KeyBasedFileProcessor -e [-a|-ai] fileName publicKeyFile.&lt;br&gt;
   * If -a is specified the output file will be "ascii-armored".
   * If -i is specified the output file will be have integrity checking added.
   * &lt;p&gt;
   * To decrypt: KeyBasedFileProcessor -d fileName secretKeyFile passPhrase.
   * &lt;p&gt;
   * Note 1: this example will silently overwrite files, nor does it pay any attention to
   * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
   * will have been used.
   * &lt;p&gt;
   * Note 2: if an empty file name has been specified in the literal data object contained in the
   * encrypted packet a file with the name filename.out will be generated in the current working directory.
   */
  public class KeyBasedFileProcessorUtil
  {
      /**
       * A simple routine that opens a key ring file and loads the first available key suitable for
       * encryption.
       * 
       * @param in
       * @return
       * @throws IOException
       * @throws PGPException
       */
      public static PGPPublicKey readPublicKey(
          InputStream    in)
          throws IOException, PGPException
      {
          in = PGPUtil.getDecoderStream(in);
  
          PGPPublicKeyRingCollection        pgpPub = new PGPPublicKeyRingCollection(in);
  
          //
          // we just loop through the collection till we find a key suitable for encryption, in the real
          // world you would probably want to be a bit smarter about this.
          //
  
          //
          // iterate through the key rings.
          //
          Iterator&lt;?&gt; rIt = pgpPub.getKeyRings();
  
          while (rIt.hasNext())
          {
              PGPPublicKeyRing    kRing = (PGPPublicKeyRing)rIt.next();    
              Iterator&lt;?&gt;                        kIt = kRing.getPublicKeys();
  
              while (kIt.hasNext())
              {
                  PGPPublicKey    k = (PGPPublicKey)kIt.next();
  
                  if (k.isEncryptionKey())
                  {
                      return k;
                  }
              }
          }
  
          throw new IllegalArgumentException("Can't find encryption key in key ring.");
      }
  
      /**
       * Search a secret key ring collection for a secret key corresponding to
       * keyID if it exists.
       * 
       * @param pgpSec a secret key ring collection.
       * @param keyID keyID we want.
       * @param pass passphrase to decrypt secret key with.
       * @return
       * @throws PGPException
       * @throws NoSuchProviderException
       */
      public static PGPPrivateKey findSecretKey(
          PGPSecretKeyRingCollection  pgpSec,
          long                        keyID,
          char[]                      pass)
          throws PGPException, NoSuchProviderException
      {    
          PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
  
          if (pgpSecKey == null)
          {
              return null;
          }
  
          return pgpSecKey.extractPrivateKey(pass, "BC");
      }
  
      /**
       * decrypt the passed in message stream
       */
      public static void decryptFile(
          InputStream in,
          InputStream keyIn,
          char[]      passwd,
          String      defaultFileName,
          String      outputPath)
          throws Exception
      {
          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 &lt;?&gt;                   it = enc.getEncryptedDataObjects();
          PGPPrivateKey               sKey = null;
          PGPPublicKeyEncryptedData   pbe = null;
          PGPSecretKeyRingCollection  pgpSec = new PGPSecretKeyRingCollection(
                  PGPUtil.getDecoderStream(keyIn));
  
          while (sKey == null &amp;&amp; it.hasNext())
          {
              pbe = (PGPPublicKeyEncryptedData)it.next();
  
              sKey = findSecretKey(pgpSec, pbe.getKeyID(), passwd);
          }
  
          if (sKey == null)
          {
              throw new IllegalArgumentException("secret key for message not found.");
          }
  
          InputStream         clear = pbe.getDataStream(sKey, "BC");
  
          PGPObjectFactory    plainFact = new PGPObjectFactory(clear);
  
          Object              message = plainFact.nextObject();
  
          if (message instanceof PGPCompressedData)
          {
              PGPCompressedData   cData = (PGPCompressedData)message;
              PGPObjectFactory    pgpFact = new PGPObjectFactory(cData.getDataStream());
  
              message = pgpFact.nextObject();
          }
  
          if (message instanceof PGPLiteralData)
          {
              PGPLiteralData      ld = (PGPLiteralData)message;
              String              outFileName = ld.getFileName();
              if (ld.getFileName().length() == 0)
              {
                  outFileName = defaultFileName;
              }
  
              //MJM: Enhancement to allow targeting of output folder for decrypted files
              if (outputPath == null || outputPath.length() &gt; 0) {
                  outFileName = outputPath + outFileName;
              }
  
              FileOutputStream    fOut = new FileOutputStream(outFileName);
  
              InputStream    unc = ld.getInputStream();
              int    ch;
  
              while ((ch = unc.read()) &gt;= 0)
              {
                  fOut.write(ch);
              }
          }
          else if (message instanceof 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())
              {
                  System.err.println("message failed integrity check");
              }
              else
              {
                  System.err.println("message integrity check passed");
              }
          }
          else
          {
              System.err.println("no message integrity check");
          }
      }
  
      public static void encryptFile(
          OutputStream    out,
          String          fileName,
          PGPPublicKey    encKey,
          boolean         armor,
          boolean         withIntegrityCheck)
          throws IOException, NoSuchProviderException
      {    
          if (armor)
          {
              out = new ArmoredOutputStream(out);
          }
  
          try
          {
              ByteArrayOutputStream       bOut = new ByteArrayOutputStream();
  
  
              PGPCompressedDataGenerator  comData = new PGPCompressedDataGenerator(
                                                                      PGPCompressedData.ZIP);
  
              PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
  
              comData.close();
  
              PGPEncryptedDataGenerator   cPk = new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5, withIntegrityCheck, new SecureRandom(), "BC");
  
              cPk.addMethod(encKey);
  
              byte[]                bytes = bOut.toByteArray();
  
              OutputStream    cOut = cPk.open(out, bytes.length);
  
              cOut.write(bytes);
  
              cOut.close();
  
              out.close();
          }
          catch (PGPException e)
          {
              System.err.println(e);
              if (e.getUnderlyingException() != null)
              {
                  e.getUnderlyingException().printStackTrace();
              }
          }
      }
  
      public static void main(
          String[] args)
          throws Exception
      {
          Security.addProvider(new BouncyCastleProvider());
  
          if (args.length == 0)
          {
              System.err.println("usage: KeyBasedFileProcessor -e|-d [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]");
              return;
          }
  
          if (args[0].equals("-e"))
          {
              if (args[1].equals("-a") || args[1].equals("-ai") || args[1].equals("-ia"))
              {
                  FileInputStream     keyIn = new FileInputStream(args[3]);
                  FileOutputStream    out = new FileOutputStream(args[2] + ".asc");
                  encryptFile(out, args[2], readPublicKey(keyIn), true, (args[1].indexOf('i') &gt; 0));
              }
              else if (args[1].equals("-i"))
              {
                  FileInputStream     keyIn = new FileInputStream(args[3]);
                  FileOutputStream    out = new FileOutputStream(args[2] + ".bpg");
                  encryptFile(out, args[2], readPublicKey(keyIn), false, true);
              }
              else
              {
                  FileInputStream     keyIn = new FileInputStream(args[2]);
                  FileOutputStream    out = new FileOutputStream(args[1] + ".bpg");
                  encryptFile(out, args[1], readPublicKey(keyIn), false, false);
              }
          }
          else if (args[0].equals("-d"))
          {
              FileInputStream    in = new FileInputStream(args[1]);
              FileInputStream    keyIn = new FileInputStream(args[2]);
              decryptFile(in, keyIn, args[3].toCharArray(), new File(args[1]).getName() + ".out", null);
          }
          else
          {
              System.err.println("usage: KeyBasedFileProcessor -d|-e [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]");
          }
      }
  }
  </code></pre>
  
  <p><a href="http://i.stack.imgur.com/ki7JW.jpg" rel="nofollow">Error MEssages</a></p>
  
  <p>here is the error messages  got when running in intelliJ</p>