Java tutorial
/* * 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 java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.security.KeyStore; import java.security.NoSuchProviderException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509CertSelector; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.mail.BodyPart; import javax.mail.Multipart; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import mitm.application.djigzo.AutoTransactDelegator; import mitm.application.djigzo.DjigzoTestUtils; import mitm.application.djigzo.User; import mitm.application.djigzo.james.mock.MockMail; import mitm.application.djigzo.james.mock.MockMailetConfig; import mitm.application.djigzo.service.SystemServices; import mitm.application.djigzo.workflow.CertificateWorkflow; import mitm.application.djigzo.workflow.KeyAndCertificateWorkflow; import mitm.application.djigzo.workflow.UserWorkflow; import mitm.common.hibernate.DatabaseActionExecutor; import mitm.common.hibernate.DatabaseActionExecutorBuilder; import mitm.common.hibernate.DatabaseException; import mitm.common.hibernate.DatabaseVoidAction; import mitm.common.hibernate.HibernateUtils; import mitm.common.hibernate.SessionManager; import mitm.common.mail.MailUtils; import mitm.common.properties.HierarchicalPropertiesException; import mitm.common.security.KeyAndCertificate; import mitm.common.security.SecurityFactoryFactory; import mitm.common.security.certificate.CertificateUtils; import mitm.common.security.certificate.X509CertificateInspector; import mitm.common.security.digest.Digest; import mitm.common.security.keystore.KeyStoreProvider; 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 mitm.common.security.smime.SMIMEUtils; import mitm.common.util.BigIntegerUtils; import org.apache.commons.lang.StringUtils; import org.apache.mailet.MailAddress; import org.hibernate.Session; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class SMIMESignTest { private final static File testBase = new File("test/resources/testdata"); private static final File tempDir = new File("test/tmp"); @BeforeClass public static void setUpBeforeClass() throws Exception { DjigzoTestUtils.initialize(); HibernateUtils.recreateTables(SystemServices.getHibernateSessionSource().getHibernateConfiguration()); CertificateWorkflow rootWorkflow = SystemServices.getKeyAndRootCertificateWorkflow(); importCertificates(rootWorkflow, new File("test/resources/testdata/certificates/mitm-test-root.cer")); addUser(); } @Before public void before() throws Exception { KeyAndCertificateWorkflow keyAndCertificateWorkflow = SystemServices.getKeyAndCertificateWorkflow(); importKeyStore(keyAndCertificateWorkflow, new File("test/resources/testdata/keys/testCertificates.p12")); } private static void importKeyStore(KeyAndCertificateWorkflow keyAndCertificateWorkflow, File pfxFile) throws Exception { KeyStore keyStore = SecurityFactoryFactory.getSecurityFactory().createKeyStore("PKCS12"); // initialize key store keyStore.load(new FileInputStream(pfxFile), "test".toCharArray()); keyAndCertificateWorkflow.importKeyStore(keyStore, KeyAndCertificateWorkflow.MissingKey.ADD_CERTIFICATE); } private static void importCertificates(CertificateWorkflow rootWorkflow, File certificateFile) throws Exception { Collection<? extends Certificate> certificates = CertificateUtils.readCertificates(certificateFile); for (Certificate certificate : certificates) { if (certificate instanceof X509Certificate) { rootWorkflow.addCertificateTransacted((X509Certificate) certificate); } } } private static void addUser() throws Exception { final SessionManager sessionManager = SystemServices.getSessionManager(); Session previousSession = sessionManager.getSession(); final File certificateFile = new File("test/resources/testdata/certificates/" + "Martijn_Brinkers_Comodo_Class_Security_Services_CA.pem.cer"); try { DatabaseActionExecutor actionExecutor = DatabaseActionExecutorBuilder .createDatabaseActionExecutor(sessionManager); actionExecutor.executeTransaction(new DatabaseVoidAction() { @Override public void doAction(Session session) throws DatabaseException { sessionManager.setSession(session); addUserAction(session, certificateFile); } }); } finally { sessionManager.setSession(previousSession); } } public static void addUserAction(Session session, File certificateFile) throws DatabaseException { UserWorkflow userWorkflow = SystemServices.getUserWorkflow(); try { User user = userWorkflow.addUser("m.brinkers@pobox.com"); userWorkflow.makePersistent(user); Collection<? extends Certificate> certificates = CertificateUtils.readCertificates(certificateFile); for (Certificate certificate : certificates) { if (certificate instanceof X509Certificate) { user.getUserPreferences().getCertificates().add((X509Certificate) certificate); } } } catch (AddressException e) { throw new DatabaseException(e); } catch (CertificateException e) { throw new DatabaseException(e); } catch (NoSuchProviderException e) { throw new DatabaseException(e); } catch (FileNotFoundException e) { throw new DatabaseException(e); } catch (HierarchicalPropertiesException e) { throw new DatabaseException(e); } } /* * Sign large message and test the performance */ @Test public void testPerformanceTest() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); int repeat = 10; long start = System.currentTimeMillis(); for (int i = 0; i < repeat; i++) { MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); assertEquals(SMIMEHeader.DETACHED_SIGNATURE_TYPE, SMIMEUtils.dissectSigned((Multipart) mail.getMessage().getContent())[1].getContentType()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.CLEAR_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); List<X509Certificate> certificates = inspector.getSignedInspector().getCertificates(); assertEquals(3, certificates.size()); assertEquals("1C1C1CF46CC9233B23391A3B9BEF558969567091", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(0), Digest.SHA1)); assertEquals("D8F8E5B92E651B1E3EF93B5493EACDE4C13AFEE0", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(1), Digest.SHA1)); assertEquals("69D7FFAF26BD5E9E4F42083BCA077BFAA8398593", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(2), Digest.SHA1)); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(Digest.SHA1.getOID(), inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); } long diff = System.currentTimeMillis() - start; double perSecond = repeat * 1000.0 / diff; System.out.println("PDF ecryptions/sec: " + perSecond); /* * NOTE: !!! can fail on a slower system * * On my Quad CPU Q8300, 100 repeats: 1.8/sec */ assertTrue("S/MIME encryption too slow. !!! this can fail on a slower system !!!", perSecond > 1); } @Test public void testNewMessageID() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailetConfig.setInitParameter("retainMessageID", "false"); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); assertEquals(SMIMEHeader.DETACHED_SIGNATURE_TYPE, SMIMEUtils.dissectSigned((Multipart) mail.getMessage().getContent())[1].getContentType()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.CLEAR_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); assertEquals(3, inspector.getSignedInspector().getCertificates().size()); assertEquals("1C1C1CF46CC9233B23391A3B9BEF558969567091", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(0), Digest.SHA1)); assertEquals("D8F8E5B92E651B1E3EF93B5493EACDE4C13AFEE0", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(1), Digest.SHA1)); assertEquals("69D7FFAF26BD5E9E4F42083BCA077BFAA8398593", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(2), Digest.SHA1)); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(Digest.SHA1.getOID(), inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); assertFalse("<123456>".equals(mail.getMessage().getMessageID())); assertTrue(mail.getMessage().getMessageID().contains("JavaMail")); } @Test public void testRetainMessageID() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); assertEquals(SMIMEHeader.DETACHED_SIGNATURE_TYPE, SMIMEUtils.dissectSigned((Multipart) mail.getMessage().getContent())[1].getContentType()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.CLEAR_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); assertEquals(3, inspector.getSignedInspector().getCertificates().size()); assertEquals("1C1C1CF46CC9233B23391A3B9BEF558969567091", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(0), Digest.SHA1)); assertEquals("D8F8E5B92E651B1E3EF93B5493EACDE4C13AFEE0", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(1), Digest.SHA1)); assertEquals("69D7FFAF26BD5E9E4F42083BCA077BFAA8398593", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(2), Digest.SHA1)); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(Digest.SHA1.getOID(), inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); assertEquals("<123456>", mail.getMessage().getMessageID()); } @Test public void testDeprecatedContentType() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailetConfig.setInitParameter("useDeprecatedContentTypes", "true"); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); assertEquals(SMIMEHeader.DEPRECATED_DETACHED_SIGNATURE_TYPE, SMIMEUtils.dissectSigned((Multipart) mail.getMessage().getContent())[1].getContentType()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.CLEAR_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); assertEquals(3, inspector.getSignedInspector().getCertificates().size()); assertEquals("1C1C1CF46CC9233B23391A3B9BEF558969567091", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(0), Digest.SHA1)); assertEquals("D8F8E5B92E651B1E3EF93B5493EACDE4C13AFEE0", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(1), Digest.SHA1)); assertEquals("69D7FFAF26BD5E9E4F42083BCA077BFAA8398593", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(2), Digest.SHA1)); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(Digest.SHA1.getOID(), inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); assertNotNull(mail.getMessage().getMessageID()); } @Test public void testInvalidFrom() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); mailetConfig.setInitParameter("catchRuntimeExceptions", "false"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail mail = new MockMail(); MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message.eml")); message.setFrom(new InternetAddress("xxx")); message.saveChanges(); mail.setMessage(message); Set<MailAddress> recipients = new HashSet<MailAddress>(); recipients.add(new MailAddress("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(null); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.NONE, inspector.getSMIMEType()); } @Test public void testKeyMissing() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); mailetConfig.setInitParameter("catchRuntimeExceptions", "false"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); /* * Remove all keys from KeyStore and try to sign again. */ KeyStoreProvider keyStoreService = SystemServices.getKeyStore(); assertNotNull(keyStoreService); Enumeration<String> aliasEnum = keyStoreService.getKeyStore().aliases(); while (aliasEnum.hasMoreElements()) { String alias = aliasEnum.nextElement(); keyStoreService.getKeyStore().deleteEntry(alias); } mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); } @Test public void testUnknownContentTransferEncoding() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail mail = new MockMail(); MimeMessage message = MailUtils .loadMessage(new File(testBase, "mail/unknown-content-transfer-encoding.eml")); mail.setMessage(message); Set<MailAddress> recipients = new HashSet<MailAddress>(); recipients.add(new MailAddress("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); } @Test public void testUnknownCharset() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail mail = new MockMail(); MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/unknown-charset-xxx.eml")); mail.setMessage(message); Set<MailAddress> recipients = new HashSet<MailAddress>(); recipients.add(new MailAddress("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); //TODO: the message is not signed and not checked. Need to add fallback charset provider } @Test public void testDefaultSettingsNoAddRoot() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); mailetConfig.setInitParameter("addRoot", "false"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.CLEAR_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); assertEquals(2, inspector.getSignedInspector().getCertificates().size()); assertEquals("1C1C1CF46CC9233B23391A3B9BEF558969567091", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(0), Digest.SHA1)); assertEquals("D8F8E5B92E651B1E3EF93B5493EACDE4C13AFEE0", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(1), Digest.SHA1)); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(Digest.SHA1.getOID(), inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); } @Test public void testDefaultSettings() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); MailUtils.writeMessage(mail.getMessage(), new File(tempDir, "testDefaultSettings.eml")); assertEquals(SMIMEHeader.DETACHED_SIGNATURE_TYPE, SMIMEUtils.dissectSigned((Multipart) mail.getMessage().getContent())[1].getContentType()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.CLEAR_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); assertEquals(3, inspector.getSignedInspector().getCertificates().size()); assertEquals("1C1C1CF46CC9233B23391A3B9BEF558969567091", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(0), Digest.SHA1)); assertEquals("D8F8E5B92E651B1E3EF93B5493EACDE4C13AFEE0", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(1), Digest.SHA1)); assertEquals("69D7FFAF26BD5E9E4F42083BCA077BFAA8398593", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(2), Digest.SHA1)); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(Digest.SHA1.getOID(), inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); // check that no headers are signed. Only a content-type header should be added to the part Multipart mp = (Multipart) mail.getMessage().getContent(); assertEquals(2, mp.getCount()); BodyPart part = mp.getBodyPart(0); Enumeration<?> e = part.getNonMatchingHeaders(new String[] { "content-type" }); assertFalse(e.hasMoreElements()); } @Test public void testSenderCaseInsensitive() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("teST@EXAmple.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.CLEAR_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); assertEquals(3, inspector.getSignedInspector().getCertificates().size()); assertEquals("1C1C1CF46CC9233B23391A3B9BEF558969567091", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(0), Digest.SHA1)); assertEquals("D8F8E5B92E651B1E3EF93B5493EACDE4C13AFEE0", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(1), Digest.SHA1)); assertEquals("69D7FFAF26BD5E9E4F42083BCA077BFAA8398593", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(2), Digest.SHA1)); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(Digest.SHA1.getOID(), inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); } @Test public void testSHA512Opaque() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); mailetConfig.setInitParameter("algorithm", "SHA512WithRSA"); mailetConfig.setInitParameter("signMode", "opaque"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.OPAQUE_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); assertEquals(3, inspector.getSignedInspector().getCertificates().size()); assertEquals("1C1C1CF46CC9233B23391A3B9BEF558969567091", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(0), Digest.SHA1)); assertEquals("D8F8E5B92E651B1E3EF93B5493EACDE4C13AFEE0", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(1), Digest.SHA1)); assertEquals("69D7FFAF26BD5E9E4F42083BCA077BFAA8398593", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(2), Digest.SHA1)); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(Digest.SHA512.getOID(), inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); } /* * 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"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); } @Test public void testProtectedHeaders() throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailetConfig.setInitParameter("protectedHeader", "subject,to,from"); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); MailUtils.writeMessage(mail.getMessage(), new File(tempDir, "testProtectedHeaders.eml")); assertEquals(SMIMEHeader.DETACHED_SIGNATURE_TYPE, SMIMEUtils.dissectSigned((Multipart) mail.getMessage().getContent())[1].getContentType()); // check if some headers are signed Multipart mp = (Multipart) mail.getMessage().getContent(); assertEquals(2, mp.getCount()); BodyPart part = mp.getBodyPart(0); // there should be 3 non content-type headers Enumeration<?> e = part.getNonMatchingHeaders(new String[] { "content-type" }); int count = 0; while (e.hasMoreElements()) { e.nextElement(); count++; } assertEquals(3, count); assertEquals("test simple message", StringUtils.join(part.getHeader("subject"), ",")); assertEquals("test@example.com", StringUtils.join(part.getHeader("from"), ",")); assertEquals("test@example.com", StringUtils.join(part.getHeader("to"), ",")); } @Test public void testSignBuildPath() throws Exception { AutoTransactDelegator proxy = AutoTransactDelegator.createProxy(); /* * Find a certificate with critical EMAILPROTECTION extension */ X509CertSelector selector = new X509CertSelector(); selector.setSerialNumber(BigIntegerUtils.hexDecode("1178C3B653829E895ACB7100EB1F627")); selector.setIssuer("EMAILADDRESS=ca@example.com, CN=MITM Test CA, L=Amsterdam, ST=NH, C=NL"); List<KeyAndCertificate> keyAndCertificates = proxy.getKeyAndCertificates(selector); assertEquals(1, keyAndCertificates.size()); proxy.setUserSigningKeyAndCertificate("test@example.com", keyAndCertificates.get(0)); MockMailetConfig mailetConfig = new MockMailetConfig("test"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail 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("recipient@example.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); MailUtils.writeMessage(mail.getMessage(), new File(tempDir, "testDefaultSettings.eml")); assertEquals(SMIMEHeader.DETACHED_SIGNATURE_TYPE, SMIMEUtils.dissectSigned((Multipart) mail.getMessage().getContent())[1].getContentType()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.CLEAR_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); assertEquals(3, inspector.getSignedInspector().getCertificates().size()); assertEquals("F18CC8973F9AB82A6C47448282849A72416B6DAB", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(0), Digest.SHA1)); assertEquals("D8F8E5B92E651B1E3EF93B5493EACDE4C13AFEE0", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(1), Digest.SHA1)); assertEquals("69D7FFAF26BD5E9E4F42083BCA077BFAA8398593", X509CertificateInspector .getThumbprint(inspector.getSignedInspector().getCertificates().get(2), Digest.SHA1)); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(Digest.SHA1.getOID(), inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); // check that no headers are signed. Only a content-type header should be added to the part Multipart mp = (Multipart) mail.getMessage().getContent(); assertEquals(2, mp.getCount()); BodyPart part = mp.getBodyPart(0); Enumeration<?> e = part.getNonMatchingHeaders(new String[] { "content-type" }); assertFalse(e.hasMoreElements()); } public void sign(String signingAlgorithm, String digestOID) throws Exception { MockMailetConfig mailetConfig = new MockMailetConfig("test"); mailetConfig.setInitParameter("algorithmAttribute", "signingAlgo"); SMIMESign mailet = new SMIMESign(); mailet.init(mailetConfig); MockMail 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("m.brinkers@pobox.com")); mail.setRecipients(recipients); mail.setSender(new MailAddress("test@example.com")); mail.setAttribute("signingAlgo", signingAlgorithm); mailet.service(mail); MailUtils.validateMessage(mail.getMessage()); MailUtils.writeMessage(mail.getMessage(), new File(tempDir, "testDefaultSettings.eml")); assertEquals(SMIMEHeader.DETACHED_SIGNATURE_TYPE, SMIMEUtils.dissectSigned((Multipart) mail.getMessage().getContent())[1].getContentType()); SMIMEInspector inspector = new SMIMEInspectorImpl(mail.getMessage(), null, "BC"); assertEquals(SMIMEType.SIGNED, inspector.getSMIMEType()); assertEquals(SMIMEHeader.Type.CLEAR_SIGNED, SMIMEHeader.getSMIMEContentType(mail.getMessage())); assertEquals(3, inspector.getSignedInspector().getCertificates().size()); assertEquals(1, inspector.getSignedInspector().getSigners().size()); assertEquals(digestOID, inspector.getSignedInspector().getSigners().get(0).getDigestAlgorithmOID()); // check that no headers are signed. Only a content-type header should be added to the part Multipart mp = (Multipart) mail.getMessage().getContent(); assertEquals(2, mp.getCount()); BodyPart part = mp.getBodyPart(0); Enumeration<?> e = part.getNonMatchingHeaders(new String[] { "content-type" }); assertFalse(e.hasMoreElements()); } @Test public void testSigningAlgorithmAttribute() throws Exception { sign("MD2WITHRSA", "1.2.840.113549.2.2"); sign("MD5WITHRSA", Digest.MD5.getOID()); sign("SHA1WITHRSAENCRYPTION", Digest.SHA1.getOID()); sign("SHA224WITHRSAENCRYPTION", Digest.SHA224.getOID()); sign("SHA256WITHRSA", Digest.SHA256.getOID()); sign("SHA384WITHRSAENCRYPTION", Digest.SHA384.getOID()); sign("SHA512WITHRSA", Digest.SHA512.getOID()); sign("RIPEMD160WITHRSA", Digest.RIPEMD160.getOID()); sign("RIPEMD128WITHRSA", Digest.RIPEMD128.getOID()); sign("RIPEMD256WITHRSA", Digest.RIPEMD256.getOID()); } }