mitm.application.djigzo.james.mailets.SMIMEEncryptTest.java Source code

Java tutorial

Introduction

Here is the source code for mitm.application.djigzo.james.mailets.SMIMEEncryptTest.java

Source

/*
 * Copyright (c) 2008-2012, Martijn Brinkers, Djigzo.
 * 
 * This file is part of Djigzo email encryption.
 *
 * Djigzo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License 
 * version 3, 19 November 2007 as published by the Free Software 
 * Foundation.
 *
 * Djigzo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public 
 * License along with Djigzo. If not, see <http://www.gnu.org/licenses/>
 *
 * Additional permission under GNU AGPL version 3 section 7
 * 
 * If you modify this Program, or any covered work, by linking or 
 * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, 
 * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, 
 * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, 
 * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, 
 * wsdl4j-1.6.1.jar (or modified versions of these libraries), 
 * containing parts covered by the terms of Eclipse Public License, 
 * tyrex license, freemarker license, dom4j license, mx4j license,
 * Spice Software License, Common Development and Distribution License
 * (CDDL), Common Public License (CPL) the licensors of this Program grant 
 * you additional permission to convey the resulting work.
 */
package mitm.application.djigzo.james.mailets;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import mitm.application.djigzo.DjigzoTestUtils;
import mitm.application.djigzo.james.Certificates;
import mitm.application.djigzo.james.DjigzoMailAttributes;
import mitm.application.djigzo.james.DjigzoMailAttributesImpl;
import mitm.application.djigzo.james.mock.MockMail;
import mitm.application.djigzo.james.mock.MockMailetConfig;
import mitm.application.djigzo.service.SystemServices;
import mitm.common.hibernate.HibernateUtils;
import mitm.common.mail.MailSession;
import mitm.common.mail.MailUtils;
import mitm.common.security.SecurityFactoryFactory;
import mitm.common.security.certificate.CertificateUtils;
import mitm.common.security.keystore.KeyStoreKeyProvider;
import mitm.common.security.smime.SMIMEEncryptionAlgorithm;
import mitm.common.security.smime.SMIMEHeader;
import mitm.common.security.smime.SMIMEInspector;
import mitm.common.security.smime.SMIMEInspectorImpl;
import mitm.common.security.smime.SMIMEType;

import org.apache.commons.lang.StringUtils;
import org.apache.mailet.Mail;
import org.apache.mailet.MailAddress;
import org.junit.BeforeClass;
import org.junit.Test;

public class SMIMEEncryptTest {
    private final static File testBase = new File("test/resources/testdata");

    private static final File tempDir = new File("test/tmp");

    private static Certificates certificates;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        DjigzoTestUtils.initialize();

        HibernateUtils.recreateTables(SystemServices.getHibernateSessionSource().getHibernateConfiguration());

        Collection<X509Certificate> x509Certificates = CertificateUtils
                .readX509Certificates(new File(testBase, "certificates/testCertificates.p7b"));

        certificates = new Certificates(new HashSet<X509Certificate>(x509Certificates));
    }

    private static KeyStore loadKeyStore(File file, String password) throws Exception {
        KeyStore keyStore = SecurityFactoryFactory.getSecurityFactory().createKeyStore("PKCS12");

        keyStore.load(new FileInputStream(file), password.toCharArray());

        return keyStore;
    }

    /*
     * Encrypt large message and test the performance
     */
    @Test
    public void testPerformanceTest() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        mailetConfig.setInitParameter("algorithm", "AES128");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        int repeat = 10;

        long start = System.currentTimeMillis();

        for (int i = 0; i < repeat; i++) {
            Mail mail = new MockMail();

            MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/test-5120K.eml"));

            mail.setMessage(message);

            Set<MailAddress> recipients = new HashSet<MailAddress>();

            recipients.add(new MailAddress("test@example.com"));

            mail.setRecipients(recipients);

            DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

            mailAttributes.setCertificates(certificates);

            mailet.service(mail);

            MailUtils.validateMessage(mail.getMessage());

            SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

            assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
            assertEquals(SMIMEEncryptionAlgorithm.AES128_CBC.getOID().toString(),
                    inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
            assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());
        }

        long diff = System.currentTimeMillis() - start;

        double perSecond = repeat * 1000.0 / diff;

        System.out.println("S/MIME ecryptions/sec: " + perSecond);

        /*
         * NOTE: !!! can fail on a slower system
         * 
         * On my Quad CPU Q8300, 100 repeats: 3.16/sec
         */
        assertTrue("S/MIME encryption too slow. !!! this can fail on a slower system !!!", perSecond > 2);
    }

    /*
     * Test what happens when an invalid message (a message that fails on writeTo) is encrypted. 
     */
    @Test
    public void testCurruptMessage() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = new MimeMessage(MailSession.getDefaultSession());

        MimeBodyPart emptyPart = new MimeBodyPart();

        message.setContent(emptyPart, "text/plain");

        message.saveChanges();

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        assertEquals(message, mail.getMessage());

        try {
            MailUtils.validateMessage(message);

            fail();
        } catch (IOException e) {
            // expected. The message should be corrupt
        }
    }

    /*
     * sometime multipart messages contain a Content-Transfer-Encoding different from 7bit. This is stricly speaking
     * not allowed (according to RFCs). Javamail (until 1.4.4) does not ignore the Content-Transfer-Encoding like it
     * should. This test tests if the Content-Transfer-Encoding is ignored. This test should fail with Javamail <= 1.4.3
     * and succeed with Javamail >= 1.4.4  
     */
    @Test
    public void testMultipartWithIllegalContentTransferEncoding() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        mailetConfig.setInitParameter("algorithm", "AES128");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/quoted-printable-multipart.eml"));

        assertTrue(message.isMimeType("multipart/mixed"));

        MimeMultipart mp = (MimeMultipart) message.getContent();

        assertEquals(2, mp.getCount());

        BodyPart part = mp.getBodyPart(0);

        assertTrue(part.isMimeType("text/plain"));
        assertEquals("==", (String) part.getContent());

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        KeyStoreKeyProvider keyStore = new KeyStoreKeyProvider(
                loadKeyStore(new File("test/resources/testdata/keys/testCertificates.p12"), "test"), "test");

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), keyStore, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.AES128_CBC.getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());

        MimeMessage decrypted = inspector.getContentAsMimeMessage();

        decrypted.saveChanges();

        assertNotNull(decrypted);

        MailUtils.writeMessage(decrypted, new File(tempDir, "testMultipartWithIllegalContentTransferEncoding.eml"));

        assertTrue(decrypted.isMimeType("multipart/mixed"));

        mp = (MimeMultipart) decrypted.getContent();

        assertEquals(2, mp.getCount());

        part = mp.getBodyPart(0);

        assertTrue(part.isMimeType("text/plain"));

        /*
         * The body should not be changed to =3D=3D because the body should not be quoted-printable encoded
         * again
         */
        assertEquals("==", (String) part.getContent());
    }

    @Test
    public void testNewMessageID() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailetConfig.setInitParameter("retainMessageID", "false");

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message-with-id.eml"));

        assertEquals("<123456>", message.getMessageID());

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        assertEquals(SMIMEHeader.ENCRYPTED_CONTENT_TYPE, mail.getMessage().getContentType());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.DES_EDE3_CBC.getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());

        assertFalse("<123456>".equals(mail.getMessage().getMessageID()));
        assertTrue(mail.getMessage().getMessageID().contains("JavaMail"));
    }

    @Test
    public void testRetainMessageID() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message-with-id.eml"));

        assertEquals("<123456>", message.getMessageID());

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        assertEquals(SMIMEHeader.ENCRYPTED_CONTENT_TYPE, mail.getMessage().getContentType());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.DES_EDE3_CBC.getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());
        assertEquals("<123456>", mail.getMessage().getMessageID());
    }

    /*
     * This test tests whether an email message with unknown content-transfer-encoding can be encrypted. Javamail
     * prior to 1.4.4 (i.e. <= 1.4.3) would throw exceptions when handling unknown content-transfer-encoding's. Since
     * 1.4.4 Javamail silently ignores the unkown encoding.
     * 
     * This test has been modified to reflect the new behavior since 1.4.4
     */
    @Test
    public void testInvalidEncoding() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils
                .loadMessage(new File(testBase, "mail/unknown-content-transfer-encoding.eml"));

        assertEquals("xxx", message.getEncoding());

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        assertTrue(message != mail.getMessage());
        assertFalse("xxx".equals(mail.getMessage().getEncoding()));

        MailUtils.validateMessage(mail.getMessage());

        assertEquals(SMIMEHeader.ENCRYPTED_CONTENT_TYPE, mail.getMessage().getContentType());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.DES_EDE3_CBC.getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());
    }

    @Test
    public void testDeprecatedContentType() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailetConfig.setInitParameter("useDeprecatedContentTypes", "true");

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        assertEquals(SMIMEHeader.DEPRECATED_ENCRYPTED_CONTENT_TYPE, mail.getMessage().getContentType());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.DES_EDE3_CBC.getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());
        assertTrue(mail.getMessage().getMessageID().contains("JavaMail"));
    }

    @Test
    public void testOnlyAttachment() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        mailetConfig.setInitParameter("algorithm", "AES128");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/only-attachment.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.AES128_CBC.getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());
    }

    @Test
    public void testNullMessage() throws MessagingException {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);
    }

    @Test
    public void testDefaultSettings() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        assertEquals(SMIMEHeader.ENCRYPTED_CONTENT_TYPE, mail.getMessage().getContentType());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.DES_EDE3_CBC.getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());
    }

    @Test
    public void testAES() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        mailetConfig.setInitParameter("algorithm", "AES128");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.AES128_CBC.getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());
    }

    @Test
    public void testRC2KeySize() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        mailetConfig.setInitParameter("algorithm", "RC2");
        mailetConfig.setInitParameter("keySize", "56");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.RC2_CBC.getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());

        assertEquals(128, SMIMEEncryptionAlgorithm.getKeySize(SMIMEEncryptionAlgorithm.RC2_CBC,
                inspector.getEnvelopedInspector().getEncryptionAlgorithmParameters()));

        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());
    }

    @Test
    public void testRecipientMode() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        mailetConfig.setInitParameter("recipientMode", "BOTH");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC");

        // there are 10 certificates with a subjectKeyIdentifier so 20 + 10 = 30
        assertEquals(30, inspector.getEnvelopedInspector().getRecipients().size());
    }

    /*
     * Checks if setting catchRuntimeExceptions and catchErrors is allowed
     */
    @Test
    public void testSetBaseParameters() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        mailetConfig.setInitParameter("catchRuntimeExceptions", "true");
        mailetConfig.setInitParameter("catchErrors", "true");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);
    }

    /*
     * Check if setting an empty protectedHeader is allowed
     */
    @Test
    public void testSetEmptyProctectedHeader() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        mailetConfig.setInitParameter("protectedHeader", "");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        assertTrue(Arrays.equals(new String[] { "" }, mailet.getProtectedHeaders()));
    }

    @Test
    public void testProtectedHeadersStatic() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailetConfig.setInitParameter("retainMessageID", "false");
        mailetConfig.setInitParameter("protectedHeader", "from, message-id");

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message-with-id.eml"));

        assertEquals("<123456>", message.getMessageID());

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MimeMessage encrypted = mail.getMessage();

        /*
         * Change from to see whether it was protected
         */
        encrypted.setFrom(new InternetAddress("changed@changed.example.com"));

        MailUtils.validateMessage(encrypted);

        assertFalse("<123456>".equals(encrypted.getMessageID()));

        assertEquals(SMIMEHeader.ENCRYPTED_CONTENT_TYPE, encrypted.getContentType());

        KeyStoreKeyProvider keyStore = new KeyStoreKeyProvider(
                loadKeyStore(new File("test/resources/testdata/keys/testCertificates.p12"), "test"), "test");

        SMIMEInspector inspector = new SMIMEInspectorImpl(encrypted, keyStore, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());

        /*
         * now decrypt and check whether message-id and from was protected
         */
        MimeMessage decrypted = inspector.getContentAsMimeMessage();

        inspector = new SMIMEInspectorImpl(decrypted, keyStore, "BC");

        assertEquals(SMIMEType.NONE, inspector.getSMIMEType());

        assertTrue("<123456>".equals(decrypted.getMessageID()));
        assertEquals("test@example.com", StringUtils.join(decrypted.getFrom()));
    }

    @Test
    public void testProtectedHeadersMailAttributes() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailetConfig.setInitParameter("retainMessageID", "false");

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail);

        /*
         * set protected headers in the mail attributes
         */
        mailAttributes.setProtectedHeaders(new String[] { "from", "message-id" });

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message-with-id.eml"));

        assertEquals("<123456>", message.getMessageID());

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        mailAttributes.setCertificates(certificates);

        mailet.service(mail);

        MimeMessage encrypted = mail.getMessage();

        /*
         * Change from to see whether it was protected
         */
        encrypted.setFrom(new InternetAddress("changed@changed.example.com"));

        MailUtils.validateMessage(encrypted);

        assertFalse("<123456>".equals(encrypted.getMessageID()));

        assertEquals(SMIMEHeader.ENCRYPTED_CONTENT_TYPE, encrypted.getContentType());

        KeyStoreKeyProvider keyStore = new KeyStoreKeyProvider(
                loadKeyStore(new File("test/resources/testdata/keys/testCertificates.p12"), "test"), "test");

        SMIMEInspector inspector = new SMIMEInspectorImpl(encrypted, keyStore, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());

        /*
         * now decrypt and check whether message-id and from was protected
         */
        MimeMessage decrypted = inspector.getContentAsMimeMessage();

        inspector = new SMIMEInspectorImpl(decrypted, keyStore, "BC");

        assertEquals(SMIMEType.NONE, inspector.getSMIMEType());

        assertTrue("<123456>".equals(decrypted.getMessageID()));
        assertEquals("test@example.com", StringUtils.join(decrypted.getFrom()));
    }

    /*
     * Called by testAlgorithmAttribute 
     */
    private void encrypt(String algorithm, KeyStoreKeyProvider keyStore) throws Exception {
        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message.eml"));

        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        mailetConfig.setInitParameter("algorithm", "3DES");
        mailetConfig.setInitParameter("algorithmAttribute", "algorithm");

        SMIMEEncrypt mailet = new SMIMEEncrypt();

        mailet.init(mailetConfig);

        Mail mail = new MockMail();

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("test@example.com"));

        mail.setRecipients(recipients);

        DjigzoMailAttributesImpl mailAttributes = new DjigzoMailAttributesImpl(mail);

        mailAttributes.setCertificates(certificates);

        mail.setAttribute("algorithm", algorithm);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), keyStore, "BC");

        assertEquals(SMIMEType.ENCRYPTED, inspector.getSMIMEType());
        assertEquals(SMIMEEncryptionAlgorithm.fromName(algorithm).getOID().toString(),
                inspector.getEnvelopedInspector().getEncryptionAlgorithmOID());
        assertEquals(20, inspector.getEnvelopedInspector().getRecipients().size());

        MimeMessage decrypted = inspector.getContentAsMimeMessage();

        assertEquals("test", ((String) decrypted.getContent()).trim());
    }

    @Test
    public void testAlgorithmAttribute() throws Exception {
        KeyStoreKeyProvider keyStore = new KeyStoreKeyProvider(
                loadKeyStore(new File("test/resources/testdata/keys/testCertificates.p12"), "test"), "test");

        for (SMIMEEncryptionAlgorithm algorithm : SMIMEEncryptionAlgorithm.values()) {
            System.out.println("Using algorithm " + algorithm);

            encrypt(algorithm.getName(), keyStore);
        }
    }
}