PGP/MIME with Java


As of version 2.7.0.1 DidiSoft OpenPGP Library for Java provides a separate JAR file located under [product ZIP]\Library\Mail\pgplib-mail-<version>.jar and offering PGP/MIME email functionality.

In this tutorial we will illustrate how to utilize the classes located in the above JAR file in order to exchange PGP/MIME email messages with other systems that support this format (e.g. Symantec Messaging Gateway, Z1 SecureMail Gateway, Enigmail, etc.).

Online Javadoc is available here

Table of contents
1. Setup
2. Sending encrypted email
3. Receiving encrypted email
4. Signed email
5. Signed and encrypted email

Setup

You have to include the JAR files listed below in the class path of your Java application:

[product ZIP archive]\Library\Mail\pgplib-mail-x.x.x.jar
[product ZIP archive]\Library\Mail\javax.mail.jar – you can skip this file if it’s already in your classpath

2. Sending encrypted email

The main class offering PGP/MIME functionality is com.didisoft.pgp.mail.PGPMailUtils. It provides encrypting methods similar to the ones provided by PGPLib and works with keys located in files, provided as inline strings or located in a KeyStore.

The example below shows how to produce a javax.mail.internet.MimeMessage OpenPGP encrypted with a public key located in a file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
import com.didisoft.pgp.mail.PGPMailUtils;
 
public class SendEncryptedMail {
 public static void main(String[] args) {
      // Recipient's email
      String to = "recipient@company.com";
      // Sender email
      String from = "sender@didisoft.com";
 
      Properties properties = System.getProperties();
      properties.setProperty("mail.smtp.host", "mail.didisoft.com");
      properties.setProperty("mail.smtp.port", "25");
 
      properties.setProperty("mail.user", "sender@didisoft.com");
      properties.setProperty("mail.password", "mail password");	      
 
      // Get the default Session object.
      Session session = Session.getDefaultInstance(properties);
 
      try{
         // Create a default MimeMessage object.
         MimeMessage message = new MimeMessage(session);
         message.setFrom(new InternetAddress(from));
         message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
 
         // Set Subject: header field
         message.setSubject("This is the Subject Line!");
 
         // Now set the actual message
         message.setText("This is actual message");
 
         // PGP encrypt here the message
         PGPMailLib mailUtil = new PGPMailLib();
         String publicKeyFileName = "c:\\Keys\\public_key.asc";
         MimeMessage pgpMessage = mailUtil.encryptMessage(session, message, publicKeyFileName); 
         // Send message
         Transport.send(pgpMessage);
         System.out.println("Sent message successfully....");
      }catch (Exception ex) {
         ex.printStackTrace();	         
      }
 }
}

1. Receiving encrypted mail

The receiving of PGP/MIME encrypted message consists of actually decrypting it and handling the extracted message like an ordinary received mail:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import java.io.IOException;  
import java.util.Properties;  
import javax.activation.DataHandler;
import javax.mail.*;
import javax.mail.internet.*;
import com.sun.mail.pop3.POP3Store;  
 
import com.didisoft.pgp.mail.*;
 
public class ReceiveEncryptedMail {
 
 private boolean textIsHtml = false;
 
 /** Handling MIME parts */	
 private String getText(Part p) throws MessagingException, IOException {
	if (p.isMimeType("text/*")) {
		String s = (String) p.getContent();
		textIsHtml = p.isMimeType("text/html");
		return s;
	}
 
	if (p.isMimeType("multipart/alternative")) {
		// prefer html text over plain text
		Multipart mp = (Multipart) p.getContent();
		String text = null;
		for (int i = 0; i < mp.getCount(); i++) {
			Part bp = mp.getBodyPart(i);
			if (bp.isMimeType("text/plain")) {
				if (text == null)
					text = getText(bp);
				continue;
			} else if (bp.isMimeType("text/html")) {
				String s = getText(bp);
				if (s != null)
					return s;
			} else {
				return getText(bp);
			}
		}
		return text;
	} else if (p.isMimeType("multipart/*")) {
		Multipart mp = (Multipart) p.getContent();
		for (int i = 0; i < mp.getCount(); i++) {
			String s = getText(mp.getBodyPart(i));
			if (s != null)
				return s;
		}
	}
 
	return null;
 }	
 
 public void receiveEmail(String pop3Host, 
				String user, 
				String password) {
 
	 try {
	   Properties properties = new Properties();  
	   properties.put("mail.pop3.host", pop3Host);  
	   Session emailSession = Session.getDefaultInstance(properties);  
 
	   //2) create the POP3 store object and connect with the pop server  
	   POP3Store emailStore = (POP3Store) emailSession.getStore("pop3");  
	   emailStore.connect(user, password);  
 
	   //3) create the folder object and open it  
	   Folder emailFolder = emailStore.getFolder("INBOX");  
	   emailFolder.open(Folder.READ_ONLY);  
 
	   //4) retrieve the messages from the folder in an array and print it  
	   Message[] messages = emailFolder.getMessages();  
	   for (int i = 0; i < messages.length; i++) {  
	    Message message = messages[i];  
 
	    System.out.println("Email Number " + (i + 1));  
	    System.out.println("Subject: " + message.getSubject());  
	    System.out.println("From: " + message.getFrom()[0]);  
 
	    PGPMailLib mailUtil = new PGPMailLib();
	    if (mailUtil.isOpenPGPEncrypted(message)) {
 
	    	try {
	    		MimeMessage decrypted = 
                           mailUtil.decryptMessage(emailSession,                                                    (MimeMessage)message, 
                                                   "c:\\PGPKeys\\private_key.asc", 
                                                   "changeit");
 
	    		Object decryptedRawContent = decrypted.getContent(); 
                        if (decryptedRawContent instanceof Multipart) {
                           Multipart multipart = (Multipart) decryptedRawContent;
 
                           BodyPart bodyPart = multipart.getBodyPart(0);
                           String messageText = getText(bodyPart);
 
                           System.out.print("Decrypted message: ");
                           System.out.println(messageText);
 
                           if (mailUtil.hasAttachments(decrypted)) {
                            for (int j = 1; j < multipart.getCount(); j++) {
                             BodyPart attachment = multipart.getBodyPart(j);
 
                             DataHandler handler = attachment.getDataHandler();
                             System.out.println("Attachment file name is : " + handler.getName()); 
                             // save here the file ... ((MimeBodyPart)attachment).saveFile(...)
                           }
                          } 
                      } else {
                      // pgp inline mail with no attachments, just print the decrypted text then
                      String content = decryptedRawContent.toString();
                      System.out.println(content);
                     } 
	    	} catch (Exception e) {
	    		System.out.println(e.getMessage());
	    	}
	    } else if (mailUtil.isOpenPGPSigned(message)) {
	    	// pgp signed only message
	    	MimeBodyPart decrypted = mailUtil.getSignedContent(message);
	        String content = getText(decrypted);
	        System.out.println(content);
	    } else {
	    	System.out.println(message.getContentType());
	    }
	   }  
 
	   //5) close the store and folder objects  
	   emailFolder.close(false);  
	   emailStore.close();  
 
	  } catch (NoSuchProviderException e) {e.printStackTrace();}   
	  catch (MessagingException e) {e.printStackTrace();}  
	  catch (IOException e) {e.printStackTrace();}  
	 }
 
	public static void main(String[] a) {
		ReceiveEncryptedMail receiveDemo = new ReceiveEncryptedMail();
		receiveDemo.receiveEmail("mail.mysite.com", "myname@mysite.com", "my mail password");
	}	
}

Sending PGP/MIME signed emails with Java

The sending of PGP/MIME signed email is quite easy with DidiSoft OpenPGP Library for Java. Again the whole process consists of constructing the initial email message as it should look like to the recipient and afterwards transforming it to PGP/MIME signed format transparently by invoking PGPMailLib.signMessage:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
import com.didisoft.pgp.mail.PGPMailLib;
 
public class SendSignedMail {
 
	public static void main(String[] args) {
		  // Recipient's email
	      String to = "recipient@company.com";
	      // Sender email
	      String from = "me@organization.com";
 
	      // SMTP host
	      String host = "mail.organization.com";
 
	      Properties properties = System.getProperties();
	      properties.setProperty("mail.smtp.host", host);
	      properties.setProperty("mail.smtp.port", "25");
 
	      properties.setProperty("mail.user", from);
	      properties.setProperty("mail.password", "my SMTP password");	      
 
	      // Get the default Session object.
	      Session session = Session.getDefaultInstance(properties);
 
	      try{
	         // Create a default MimeMessage object.
	         MimeMessage message = new MimeMessage(session);
	         message.setFrom(new InternetAddress(from));
	         message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
 
	         // Set Subject: header field
	         message.setSubject("This is the Subject Line!");
 
	         // Now set the actual message
	         message.setText("This is the actual message");
 
	         // PGP encrypt here the message
	         PGPMailLib mailUtil = new PGPMailLib();
	         String privateKeyFileName = "examples/DataFiles/private.key";
	         String privateKeyPassword = "changeit";
	         MimeMessage pgpMessage = mailUtil.signMessage(session, message, privateKeyFileName, privateKeyPassword); 
	         // Send message
	         Transport.send(pgpMessage);
	         System.out.println("Sent message successfully....");
	      }catch (com.didisoft.pgp.PGPException ex) {
		     ex.printStackTrace(); // PGP error	         
	      }catch (java.io.IOException ex) {
		     ex.printStackTrace(); // I/O error	         
	      }catch (MessagingException mex) {
	         mex.printStackTrace(); // Mail transport error
	      }
	 }
}

Sending PGP/MIME signed and encrypted emails with Java

Signed and encrypted PGP/MIME email according to the PGP/MIME specification can be first signed and then encrypted or using the OpenPGP signed and encrypted format. The PGPMailLib.signAndEncryptMessage method produces OpenPGP signed and encrypted format:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
import com.didisoft.pgp.mail.PGPMailLib;
 
public class SendSignedMail {
 
	public static void main(String[] args) {
		  // Recipient's email
	      String to = "recipient@company.com";
	      // Sender email
	      String from = "me@organization.com";
 
	      // SMTP host
	      String host = "mail.organization.com";
 
	      Properties properties = System.getProperties();
	      properties.setProperty("mail.smtp.host", host);
	      properties.setProperty("mail.smtp.port", "25");
 
	      properties.setProperty("mail.user", from);
	      properties.setProperty("mail.password", "my SMTP password");	      
 
	      // Get the default Session object.
	      Session session = Session.getDefaultInstance(properties);
 
	      try{
	         // Create a default MimeMessage object.
	         MimeMessage message = new MimeMessage(session);
	         message.setFrom(new InternetAddress(from));
	         message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
 
	         // Set Subject: header field
	         message.setSubject("This is the Subject Line!");
 
	         // Now set the actual message
	         message.setText("This is the actual message");
 
	         // PGP encrypt here the message
	         PGPMailLib mailUtil = new PGPMailLib();
	         String privateKeyFileName = "examples/DataFiles/private.key";
	         String privateKeyPassword = "changeit";
                 String publicKeyFileName = "examples/DataFiles/public.key";	         MimeMessage pgpMessage = mailUtil.signAndEncryptMessage(session, message, privateKeyFileName, privateKeyPassword, publicKeyFileName);
 
	         // Send message
	         Transport.send(pgpMessage);
	         System.out.println("Sent message successfully....");
	      }catch (com.didisoft.pgp.PGPException ex) {
		     ex.printStackTrace(); // PGP error	         
	      }catch (java.io.IOException ex) {
		     ex.printStackTrace(); // I/O error	         
	      }catch (MessagingException mex) {
	         mex.printStackTrace(); // Mail transport error
	      }
	 }
}

Summary

This article demonstrated the basics of the PGP/MIME functionality provided by OpenPGP Library for Java. These functions are provided by the com.didisoft.pgp.mail.PGPMailUtils class located in additional JAR file.