pgp encryption in Java

Encryption is the most widely used function of the OpenPGP cryptography. In order to encrypt a file we need the public key of the recipient(s). Another option is to conventionally encrypt only with a password.

The first OpenPGP implementations, starting with the original PGP 2.x, used to encrypt only one data file into a single encrypted file. Newer implementations can store multiple files and folders into a single encrypted file.

With OpenPGP Library for Java we have two options. The first one is to keep the recipient’s public key in a file on the disk. The second option is to store it in a KeyStore object.

Encrypt a file

1. With recipient’s public key located in a file
2. With recipient’s public key located in a KeyStore

Encrypt a Stream

3. With recipient’s public key located in a stream
4. With recipient’s public key located in a KeyStore

Encrypt a String

5. With recipient’s public key located in a file
6. With recipient’s public key located in a KeyStore

Encrypt multiple files

7. With recipient’s public key located in a file(s)  
8. With recipient’s public key located in a KeyStore

Appendix: Exception handling

1. Encrypt file with recipient’s public key located in a file

This example shows how to encrypt a data file, having the recipient’s public key in a file. In our case the recipient’s public key file has extension .key, but it can be anything else. The most common public key file name extensions are: *.asc, *.pgp, *.pgpkey.

import com.didisoft.pgp.PGPLib;
 
public class EncryptFile {
  public static void main(String[] args) throws Exception{
    // create an instance of the library
    PGPLib pgp = new PGPLib();
 
    // is output ASCII or binary
    boolean asciiArmor = false;
    // should integrity check information be added
    // set to true for compatibility with GnuPG 2.2.8+
    boolean withIntegrityCheck = false;
 
    pgp.encryptFile("INPUT.txt",
                   "public.key",
                   "OUTPUT.pgp",
                    asciiArmor,
                    withIntegrityCheck);    
  }
}

All encrypt methods have two additional parameters:

asciiArmor specifies the format of the result file, when true the file is in ASCII armored format suitable for Email attachments, when false the output file is in binary format.

When withIntegrityCheck is true additional integrity check information is appended to the encrypted file. Set to false for compatibility with older versions of PGP such as 6.5.8.

2. Encrypt file with recipient’s public key located in a KeyStore

We should choose to store our OpenPGP keys in a KeyStore object when we need additional layer of security. This example shows how to encrypt a file with public key located in a key store. ( Note that a key with UserId  demo@didisoft.com should already be imported in the KeyStore file.)

import com.didisoft.pgp.KeyStore;
import com.didisoft.pgp.PGPLib;
public class KeystoreEncryptFile {
 public static void main(String[] args) throws Exception{
  // create an instance of the KeyStore
  KeyStore keyStore = new KeyStore("pgp.keystore", "changeit");
 
  // create an instance of the library
  PGPLib pgp = new PGPLib();	
 
  String recipientUserId = "demo@didisoft.com";
 
  // is output ASCII or binary
  boolean asciiArmor = true;
  // should integrity check information be added
  // set to true for compatibility with GnuPG 2.2.8+
  boolean withIntegrityCheck = false; 
 
  pgp.encryptFile("INPUT.txt",
		keyStore,
		recipientUserId,
		"encrypted.pgp",
		asciiArmor,
		withIntegrityCheck);
  }
}

Back to Top

3. Encrypt stream with recipient’s public key located in a file

This example shows how to encrypt a stream. This way we can encrypt not only files but any other source that can be read as a stream.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
 
import com.didisoft.pgp.PGPLib;
 
public class EncryptStream {
 public static void main(String[] args) throws Exception{
  // create an instance of the library
  PGPLib pgp = new PGPLib();
 
  // is output ASCII or binary
  boolean asciiArmor = true; 
 
  // should integrity check information be added
  // set to true for compatibility with GnuPG 2.2.8+
  boolean withIntegrityCheck = false; 
 
  // obtain the streams
  InputStream inStream = new FileInputStream("INPUT.txt");
  InputStream keyStream = new FileInputStream("public.key");
  OutputStream outStream = new FileOutputStream("encrypted.pgp");
 
  // Here "INPUT.txt" is just a string to be written in the
  // OpenPGP packet which contains:
  // file name string, timestamp, and the actual data bytes
  pgp.encryptStream(inStream, "INPUT.txt",
                    keyStream,
                    outStream,
                    asciiArmor,
                    withIntegrityCheck);
 }
}

4. Encrypt stream with recipient’s public key located in a KeyStore

In this example the message source and the encrypted output are streams too. The public key of the recipient is located in a KeyStore file.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
 
import com.didisoft.pgp.KeyStore;
import com.didisoft.pgp.PGPLib;
 
public class KeyStoreEncryptStream {
 public static void main(String[] args) throws Exception{
  // create an instance of the KeyStore
  KeyStore keyStore = new KeyStore("pgp.keystore", "changeit");
 
  String recipientUserId = "demo@didisoft.com";
 
  // create an instance of the library
  PGPLib pgp = new PGPLib();
 
  // is output ASCII or binary
  boolean asciiArmor = true;
  // should integrity check information be added
  // set to true for compatibility with GnuPG 2.2.8+
  boolean withIntegrityCheck = false; 
 
  // obtain the streams
  InputStream inStream = new FileInputStream("INPUT.txt");
  OutputStream outStream = new FileOutputStream("encrypted.pgp");
 
  // Here "INPUT.txt" is just a string to be written in the
  // OpenPGP data packet which contains:
  // file name string, timestamp, and the actual data bytes
  pgp.encryptStream(inStream, "INPUT.txt",
			keyStore,
			recipientUserId,
			outStream,
			asciiArmor,
			withIntegrityCheck);
 }
}

Back to Top

5. Encrypt a String message

With the help of the library we can easily encrypt a String message:

 

import com.didisoft.pgp.PGPLib;
 
public class EncryptStringDemo {
    public static void main(String[] args) throws Exception {
        String stringToEncrypt = "the quick brown fox jumps"; 
 
        // create an instance of the library
        PGPLib pgp = new PGPLib();
 
        String publicEncryptionKeyFile = "c:\\recipient_public_key.asc";        
 
        InputStream publicEncryptionKeyStream = null;
        try {
       	publicEncryptionKeyStream = new FileInputStream(publicKeyFileName);
 
        // encrypt
        String encryptedString = 
             pgp.encryptString(stringToEncrypt,
                               publicEncryptionKeyStream);
       } finally {
             if (publicEncryptionKeyStream != null)
             	publicEncryptionKeyStream.close();
       }      
   }
}

Back to Top

6. Encrypt a String message with recipient’s public key located in a KeyStore

This example is similar to the above one but now the recipient’s public key is located in a KeyStore.

import com.didisoft.pgp.PGPLib;
 
public class EncryptStringDemo {
    public static void main(String[] args) throws Exception {
        String stringToEncrypt = "the quick brown fox jumps"; 
 
        // create an instance of the library
        PGPLib pgp = new PGPLib();
 
        KeyStore keystore = KeyStore.openFile("c:\\mylocal.keystore", "my password");        
 
        // encrypt
        String encryptedString = 
             pgp.encryptString(stringToEncrypt,
                               keystore,
                               keystore.getKeyIdForKeyIdHex("A0324F1D"));
    }
}

Back to Top

7. Encrypt multiple files with public key(s) located in file(s)

Encryption of multiple files and folders is supported by the newer OpenPGP implementations (like PGP Desktop 9+) so if you plan to use this feature, please ensure that your recipients are using compatible OpenPGP software.

(This feature is available as of version 2.5.5)

import com.didisoft.pgp.*;
 
public class EncryptFilesDemo {
  public static void main(String[] args) throws Exception{
    // create an instance of the library
    PGPLib pgp = new PGPLib();
 
    // if true the output file will be in ASCII armored format,
    // otherwise will be in binary format
    boolean asciiArmor = true;
    // when true, additional integrity check information is added
    boolean withIntegrityCheck = true;
 
    // multiple files to be encrypted in one OpenPGP archive
    String[] inputFiles = {"INPUT1.txt",
                           "INPUT2.txt",
                           "INPUT3.txt"};        
 
    // for each recipient specify the location of her public key file
    String[] recipientsPublicKeys = {"public_key1.asc",
                                    "public_key2.asc",
                                    "public_key3.asc"};        
 
    pgp.encryptFiles(inputFiles,
                     recipientsPublicKeys,
                     "encrypted.pgp",
                     asciiArmor,
                     withIntegrityCheck);
  }
}

8. Encrypt multiple files with public key(s) located in a KeyStore

This example is equivalent to example (5) except that the recipients’ keys are first imported in a KeyStore object.

import com.didisoft.pgp.*;
 
public class EncryptFilesDemo {
 public static void main(String[] args) throws Exception{
  // create an instance of the library
  PGPLib pgp = new PGPLib();
 
  // if true the output file will be in ASCII armored format,
  // otherwise will be in binary format
  boolean asciiArmor = true;
  // when true, additional integrity check information is added
  boolean withIntegrityCheck = true;
 
  String[] inputFiles = {"INPUT1.txt",
			 "INPUT2.txt",
		         "INPUT3.txt"};        
 
  // KeyStore file containing the recipients' public keys
  KeyStore keyStore = new KeyStore("mykeys.keystore", "password");  
 
  // recipients' specified with User Id (Key Id can be used as well)
  String[] recipientsUserIds = {"recipient1@company.com",
				  "John Doe",
				  "Clearing House"};        
 
  pgp.encryptFiles(inputFiles,
		keyStore,
		recipientsUserIds,
		"encrypted.pgp",
		asciiArmor,
		withIntegrityCheck);
 }
}

Exception handling

All encrypt methods throw com.didisoft.pgp.PGPException.

We can catch a few sub classes of PGPException that reside in package com.didisoft.pgp.exceptions, in order to identify specific error issues. In that case PGPException must be caught last.

Below is a part of an example code that illustrates the various exception sub classes that we can expect from the encrypt methods:

import java.io.*;
import com.didisoft.pgp.*;
import com.didisoft.pgp.exceptions.*;
 
public class ExceptionDemo {
 public static void main(String[] a) {
   PGPLib pgp = new PGPLib();
   try {
     pgp.encrypt...
   } catch (IOException e) {
     // in case of I/O error
   } catch (NoPublicKeyFoundException e) {
     // the supplied public key source does not contain a public key 
   } catch (KeyIsExpiredException e) {
     // the supplied public key is expired
   } catch (KeyIsRevokedException e) {
     // the supplied public key is revoked
   } catch (PGPException e) {
     // general OpenPGP encryption error
   }
 }
}

For general information on the available exceptions that sub class com.didisoft.pgp.PGPException, please refer to the exception handling section.

Summary

In this chapter we have shown how to OpenPGP encrypt files and streams. Below is a list of the methods used in the examples:

PGPLib.encryptFile OpenPGP encrypts a file
PGPLib.encryptFiles OpenPGP encrypts multiple files into a single archive
PGPLib.encryptStream OpenPGP encrypts a stream
PGPLib.encryptString OpenPGP encrypts a String

From here you can continue to the examples that demonstrate OpenPGP decryption or to the examples’ table of contents.