Analyzing PGP/MIME emails

The basic functionality of DidiSoft OpenPGP Library for Java for generating PGP/MIME encrypted and signed email messages and for consuming them (decrypting, verifying signatures) is not enough when we want to create a more agile applications that work with PGP encrypted emails.

The additional functionality that we may need is to determine the type of an incoming email message – PGP encrypted, signed, signed and encrypted; to whom it was sent – or more specifically to whom it was encrypted (so we can pick the right decryption key), who is the creator of the signature, so we can verify them with the correct key, and etc.

This chapter described the analytical functions provided by the library that will help in the use cases mentioned above.

Determine the type of the email

Before we decide what to do with an incoming email message we have to be sure is it PGP related. Below is a short example that illustrates the possible cases with an incoming email:

1
2
3
4
5
6
7
8
9
10
MimeMessage message = ...
 
PGPMailLib mailLib = new PGPMailLib();
if (mailLib.isOpenPGPEncrypted((Message)message)) {
	System.out.println("PGP encrypted email we must decrypt it");
} else if (mailLib.isOpenPGPSigned((Message)message)) {
	System.out.println("PGP signed email we must verify the signatture");	
} else {
	System.out.println("This is not a PGP email");	
}

Getting the encryption Key ID(s) of the email

The next step that we must take in case of an encrypted email is to determine which private key (in case our application deals with with more than one private key) must be used for decrypting the email contents. In the ideal situation the email address of the recipient must match the User ID of the PGP private key which usually follows the same pattern as email addresses “Person Name <personemail@website>” but in reality this is not always the case. This is why the com.didisoft.pgp.mail.PGPMailInspectLib class provides methods to retrieve the encryption Key ID(s). Here is an example how to utilize that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
MimeMessage message = ...
 
long[] encryptionKeyIds = inspectLib.listEncryptionKeyIds(message);
PGPMailInspectLib inspectLib = new PGPMailInspectLib();
// search do we have any of the encryption keys
KeyStore ks = new KeyStore(); // probably loaded from a file or database
for (int i = 0; i < encryptionKeyIds.length; i++) {
	KeyPairInformation key = ks.getKey(encryptionKeyIds[i]);
	// if we have the private key
	if (key != null && key.hasPrivateKey())
	{
		// we can use this private key to decrypt the message
		String keyPassword = "...";
		MimeMessage originalMessage = mailLib.decryptMessage(message, ks, keyPassword);
	}
}

Get the signing Key ID of the email

When we receive a signed PGP email we must determine which public key we must use in order to verify the digital signature. The case with the Email sender address and the public key User ID is the same as the above mentioned. But in order to be certain which key shall be used, and not rely only on a sole match of email sender address and key User ID we can use again a method of com.didisoft.pgp.mail.PGPMailInspectLib class. Here is a short example that illustrates how to apply this logic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
MimeMessage message = ...
SignatureItem[] signatures = inspectLib.listSignatures(message);
PGPMailInspectLib inspectLib = new PGPMailInspectLib();
KeyStore ks = new KeyStore(); // probably loaded from a file or database
// search do we have any of the signing keys
for (int i = 0; i < signatures.length; i++) {
	KeyPairInformation key = ks.getKey(signatures[i].getKeyId());
	// if we have this key
	if (key != null)
	{
		SignatureCheckResult signatureCheck = mailLib.verifyMessage(message, ks);
		if (signatureCheck.equals(SignatureCheckResult.SignatureVerified))
		{
			System.out.println("Signature Verified OK");
		}
	}				
}

Summary

This chapter demonstrated the usage of com.didisoft.pgp.mail.PGPMailLib and com.didisoft.pgp.mail.PGPMailInspectLib classes in order to determine the type of an incoming email and obtain information do we have suitable private key for decrypting and public key for verifying its digital signature.

Knowing the above information for a given email message we can proceed further with its handling by decrypting it.

List of methods used

PGPMailLib.isOpenPGPEncrypted returns true if an instance of javax.mail.Message is PGP encrypted
PGPMailLib.isOpenPGPSigned returns true if an instance of javax.mail.Message is PGP signed
PGPMailInspectLib.listEncryptionKeyIds returns array of raw Key ID(s) of the keys encrypted given PGP email message
PGPMailInspectLib.listSignatures returns array of com.didisoft.pgp.inspect.SignatureItem objects for each digital signature found in a PGP signed email

Javadoc

Javadoc for the above mentioned classes and methods can be found at https://sdk.didisoft.com/pgpmime/