Jan 2, 2014

smime certificate management and bouncycastle S/MIME encrypted Message/EMail creation

After having difficulties with PGP encryption with the receiving side ( the key, I got is shown in 
thunderbird to miss subkeys for encryption, but the other side said, they can encrypt ??), I had to
change to S/MIME encryption.

Meaning to create a email Message in Java and encrypt the message before sending.

The basics for encryption in Java is shown in an example in bouncycastle.

But to start you need a certificate. You can create your own CA ( certificate Authority ) and create
Certificate requests, which are signed by the CA. A nice intro ( in German ) is here, which I used because
of thinking of problems with the certificate of cacert.

The other way as mentioned is cacert.org. Here you can register and create your own certificates. The
disadvantage is, that the root certificate is not contained in Firefox/Thunderbird...

To get started you need the certificate of the receiver.

This must be stored in a pkcs12 keystore, but how to create such a keystore?

I found a nice GUI for keystore handling. This tool is called Portecle.
 It is a javatool with a clean GUI.

Creating a Keystore of Type PKC12 could not import the certificate of cacert, I created.
After this I searched for a long time, but didn't find any usefull thing.

The tricky part is, to create a JKS ( Java Key Store ), import the certificate, assign an alias name you
would like to search for in the java code and change the keystore type in the Tools menu to pkcs12.
After this you can save the keystore and have a working PKCS12 keystore as requested by the
source code of bouncycastle.

The source code is quite simple:

KeyStore    ks = KeyStore.getInstance("PKCS12", "BC");
ks.load(new FileInputStream("/path/to/keystore.p12"), "KeystorePassword".toCharArray());

Enumeration e = ks.aliases();String      keyAlias = null;
while (e.hasMoreElements()){    String  alias = (String)e.nextElement();
    if (alias.equals("searchAlias"))    {        keyAlias = alias;

     Certificate cert = ks.getCertificate(keyAlias);
     MimeMessage m = new MimeMessage(session);

     m.setFrom(new InternetAddress("sender@adress"));
     m.setSubject("Test Mail for Enryption");
     m.setRecipient(Message.RecipientType.TO, new InternetAddress(        "receiver@adress") );
     m.setText("Test email with certifcate usage.");

        // create the generator for creating an smime/encrypted message
        SMIMEEnvelopedGenerator  gen = new SMIMEEnvelopedGenerator();
        gen.addRecipientInfoGenerator(new    JceKeyTransRecipientInfoGenerator((X509Certificate)cert).setProvider("BC"));

        MimeBodyPart mp = gen.generate(m, new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC).setProvider("BC").build());
m = new MimeMessage(m);
m.setContent(mp.getContent(), mp.getContentType());
FileOutputStream fous = new FileOutputStream("email.msg");

This is a short layout without any errorhandling, but using javamail and sending the MimeMessage,
thunderbird can decrypt the message after importing the private key and the certificate.

When using cacert, you have to install the created certificate from cacert.org and backup the certificate as
a PKCS12 file in the perferences/Advanced/Certificates/View Certificates/Your Certificates path.

After saving you can import this in thunderbird  perferences/Advanced/Certificates/View Certificates/.

This allows thunderbird to decrypt S/MIME encrypted messages sent by the java code.

UPDATE: if you have more receivers, just add an RecipientInfoGenerator for each receiver with:
gen.addRecipientInfoGenerator(new    JceKeyTransRecipientInfoGenerator((X509Certificate)cert).setProvider("BC"));
 and every receiver can view the email.