package org.bouncycastle.mail.smime.test; import java.io.IOException; import java.io.InputStream; import java.security.KeyPair; import java.security.PrivateKey; import java.security.Security; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; import javax.mail.Address; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.cert.jcajce.JcaCertStore; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; import org.bouncycastle.cms.CMSAlgorithm; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.SignerInformation; import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder; import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder; import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; import org.bouncycastle.cms.jcajce.JceKeyTransRecipientId; import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator; import org.bouncycastle.mail.smime.SMIMEException; import org.bouncycastle.mail.smime.SMIMESigned; import org.bouncycastle.mail.smime.SMIMESignedGenerator; import org.bouncycastle.mail.smime.SMIMEToolkit; import org.bouncycastle.openssl.jcajce.JcaPKIXIdentityBuilder; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; import org.bouncycastle.pkix.jcajce.JcaPKIXIdentity; import org.bouncycastle.util.CollectionStore; import org.bouncycastle.util.Store; public class SMIMEToolkitTest extends TestCase { static MimeBodyPart msg; static MimeBodyPart msgR; static MimeBodyPart msgRN; static String _origDN; static KeyPair _origKP; static X509Certificate _origCert; static String _signDN; static KeyPair _signKP; static X509Certificate _signCert; static String _reciDN; static KeyPair _reciKP; static X509Certificate _reciCert; private static KeyPair _signGostKP; private static X509Certificate _signGostCert; private static KeyPair _signEcDsaKP; private static X509Certificate _signEcDsaCert; private static KeyPair _signEcGostKP; private static X509Certificate _signEcGostCert; KeyPair dsaSignKP; X509Certificate dsaSignCert; KeyPair dsaOrigKP; X509Certificate dsaOrigCert; private static final String BC = "BC"; static { try { if (Security.getProvider("BC") == null) { Security.addProvider(new BouncyCastleProvider()); } msg = SMIMETestUtil.makeMimeBodyPart("Hello world!\n"); msgR = SMIMETestUtil.makeMimeBodyPart("Hello world!\r"); msgRN = SMIMETestUtil.makeMimeBodyPart("Hello world!\r\n"); _origDN = "O=Bouncy Castle, C=AU"; _origKP = CMSTestUtil.makeKeyPair(); _origCert = CMSTestUtil.makeCertificate(_origKP, _origDN, _origKP, _origDN); _signDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; _signKP = CMSTestUtil.makeKeyPair(); _signCert = CMSTestUtil.makeCertificate(_signKP, _signDN, _origKP, _origDN); _signGostKP = CMSTestUtil.makeGostKeyPair(); _signGostCert = CMSTestUtil.makeCertificate(_signGostKP, _signDN, _origKP, _origDN); _signEcDsaKP = CMSTestUtil.makeEcDsaKeyPair(); _signEcDsaCert = CMSTestUtil.makeCertificate(_signEcDsaKP, _signDN, _origKP, _origDN); _signEcGostKP = CMSTestUtil.makeEcGostKeyPair(); _signEcGostCert = CMSTestUtil.makeCertificate(_signEcGostKP, _signDN, _origKP, _origDN); _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; _reciKP = CMSTestUtil.makeKeyPair(); _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); } catch (Exception e) { throw new RuntimeException("problem setting up signed test class: " + e); } } public void testSignedMessageRecognitionMultipart() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeMultipart smm = generateMultiPartRsa("SHA1withRSA", msg, SMIMESignedGenerator.RFC3851_MICALGS); Assert.assertTrue(toolkit.isSigned(smm)); MimeMessage body = makeMimeMessage(smm); Assert.assertTrue(toolkit.isSigned(body)); } public void testSignedMessageRecognitionEncapsulated() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeBodyPart res = generateEncapsulated(); Assert.assertTrue(toolkit.isSigned(res)); MimeMessage body = makeMimeMessage(res); Assert.assertTrue(toolkit.isSigned(body)); } public void testEncryptedRecognition() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeBodyPart msg = SMIMETestUtil.makeMimeBodyPart("WallaWallaWashington"); SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator(); gen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); MimeBodyPart res = gen.generate(msg, new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); Assert.assertTrue(toolkit.isEncrypted(res)); MimeMessage body = makeMimeMessage(res); Assert.assertTrue(toolkit.isEncrypted(body)); } public void testCertificateExtractionEncapsulated() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeBodyPart res = generateEncapsulated(); SMIMESigned smimeSigned = new SMIMESigned(res); SignerInformation signerInformation = (SignerInformation)smimeSigned.getSignerInfos().getSigners().iterator().next(); assertEquals(new JcaX509CertificateHolder(_signCert), toolkit.extractCertificate(res, signerInformation)); MimeMessage body = makeMimeMessage(res); assertEquals(new JcaX509CertificateHolder(_signCert), toolkit.extractCertificate(body, signerInformation)); } public void testCertificateExtractionMultipart() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeMultipart smm = generateMultiPartRsa("SHA1withRSA", msg, SMIMESignedGenerator.RFC3851_MICALGS); SMIMESigned smimeSigned = new SMIMESigned(smm); SignerInformation signerInformation = (SignerInformation)smimeSigned.getSignerInfos().getSigners().iterator().next(); assertEquals(new JcaX509CertificateHolder(_signCert), toolkit.extractCertificate(smm, signerInformation)); MimeMessage body = makeMimeMessage(smm); assertEquals(new JcaX509CertificateHolder(_signCert), toolkit.extractCertificate(body, signerInformation)); } public void testSignedMessageVerificationMultipart() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeMultipart smm = generateMultiPartRsa("SHA1withRSA", msg, SMIMESignedGenerator.RFC3851_MICALGS); Assert.assertTrue(toolkit.isValidSignature(smm, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert))); MimeMessage body = makeMimeMessage(smm); Assert.assertTrue(toolkit.isValidSignature(body, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert))); } public void testSignedMessageVerificationEncapsulated() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeBodyPart res = generateEncapsulated(); Assert.assertTrue(toolkit.isValidSignature(res, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert))); MimeMessage body = makeMimeMessage(res); Assert.assertTrue(toolkit.isValidSignature(body, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert))); } public void testSignedMessageVerificationEncapsulatedWithPKIXIdentity() throws Exception { JcaPKIXIdentity identity = openIdentityResource("smimeTKkey.pem", "smimeTKcert.pem"); SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); List certList = new ArrayList(); certList.add(identity.getCertificate()); Store certs = new CollectionStore(certList); SMIMESignedGenerator gen = new SMIMESignedGenerator(); gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", identity.getPrivateKey(), identity.getX509Certificate())); gen.addCertificates(certs); MimeBodyPart res = gen.generateEncapsulated(msg); Assert.assertTrue(toolkit.isValidSignature(res, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(identity.getCertificate()))); MimeMessage body = makeMimeMessage(res); Assert.assertTrue(toolkit.isValidSignature(body, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(identity.getCertificate()))); Assert.assertTrue(toolkit.isValidSignature(body, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(identity.getX509Certificate()))); } public void testEncryptedMimeBodyPart() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeBodyPart res = toolkit.encrypt(msg, new JceCMSContentEncryptorBuilder(NISTObjectIdentifiers.id_aes128_CBC).setProvider(BC).build(), new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); Assert.assertTrue(toolkit.isEncrypted(res)); MimeBodyPart dec = toolkit.decrypt(res, new JceKeyTransRecipientId(_reciCert), new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); SMIMETestUtil.verifyMessageBytes(msg, dec); } public void testEncryptedMimeBodyPartWithPKIXIdentity() throws Exception { JcaPKIXIdentity identity = openIdentityResource("smimeTKkey.pem", "smimeTKcert.pem"); SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeBodyPart res = toolkit.encrypt(msg, new JceCMSContentEncryptorBuilder(NISTObjectIdentifiers.id_aes128_CBC).setProvider(BC).build(), new JceKeyTransRecipientInfoGenerator(identity.getX509Certificate()).setProvider(BC)); Assert.assertTrue(toolkit.isEncrypted(res)); MimeBodyPart dec = toolkit.decrypt(res, identity.getRecipientId(), new JceKeyTransEnvelopedRecipient(identity.getPrivateKey()).setProvider(BC)); SMIMETestUtil.verifyMessageBytes(msg, dec); } public void testEncryptedMessage() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeMessage message = makeMimeMessage(msg); MimeBodyPart res = toolkit.encrypt(message, new JceCMSContentEncryptorBuilder(NISTObjectIdentifiers.id_aes128_CBC).setProvider(BC).build(), new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); Assert.assertTrue(toolkit.isEncrypted(res)); MimeMessage body = makeMimeMessage(res); MimeBodyPart dec = toolkit.decrypt(body, new JceKeyTransRecipientId(_reciCert), new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); SMIMETestUtil.verifyMessageBytes(message, dec); } public void testEncryptedSignedMultipart() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeBodyPart res = signEncrypt(msg, _signKP.getPrivate(), _signCert, _reciCert); Assert.assertTrue(toolkit.isEncrypted(res)); MimeMessage body = makeMimeMessage(res); MimeBodyPart dec = toolkit.decrypt(body, new JceKeyTransRecipientId(_reciCert), new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)); Assert.assertTrue(toolkit.isSigned(dec)); Assert.assertTrue(toolkit.isValidSignature(dec, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert))); SMIMETestUtil.verifyMessageBytes(msg, (MimeBodyPart)((MimeMultipart)dec.getContent()).getBodyPart(0)); } private MimeBodyPart signEncrypt(MimeBodyPart msg, PrivateKey signerKey, X509Certificate signerCert, X509Certificate recipientCert) throws OperatorCreationException, CertificateEncodingException, SMIMEException, CMSException, MessagingException { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeMultipart smm = toolkit.sign(msg, new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", signerKey, signerCert)); return toolkit.encrypt(smm, new JceCMSContentEncryptorBuilder(NISTObjectIdentifiers.id_aes128_CBC).setProvider(BC).build(), new JceKeyTransRecipientInfoGenerator(recipientCert).setProvider(BC)); } public void testSignedMessageGenerationMultipart() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeMultipart smm = toolkit.sign(msg, new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", _signKP.getPrivate(), _signCert)); Assert.assertTrue(toolkit.isValidSignature(smm, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert))); SMIMESigned smimeSigned = new SMIMESigned(smm); SignerInformation signerInformation = (SignerInformation)smimeSigned.getSignerInfos().getSigners().iterator().next(); assertEquals(new JcaX509CertificateHolder(_signCert), toolkit.extractCertificate(smm, signerInformation)); Properties props = System.getProperties(); Session session = Session.getDefaultInstance(props, null); Address fromUser = new InternetAddress("\"Eric H. Echidna\"<eric@bouncycastle.org>"); Address toUser = new InternetAddress("example@bouncycastle.org"); MimeMessage body = new MimeMessage(session); body.setFrom(fromUser); body.setRecipient(Message.RecipientType.TO, toUser); body.setSubject("example signed message"); body.setContent(smm, smm.getContentType()); body.saveChanges(); Assert.assertTrue(toolkit.isValidSignature(body, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert))); } public void testSignedMessageGenerationEncapsulated() throws Exception { SMIMEToolkit toolkit = new SMIMEToolkit(new BcDigestCalculatorProvider()); MimeBodyPart res = toolkit.signEncapsulated(msg, new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", _signKP.getPrivate(), _signCert)); Assert.assertTrue(toolkit.isValidSignature(res, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert))); SMIMESigned smimeSigned = new SMIMESigned(res); SignerInformation signerInformation = (SignerInformation)smimeSigned.getSignerInfos().getSigners().iterator().next(); assertEquals(new JcaX509CertificateHolder(_signCert), toolkit.extractCertificate(res, signerInformation)); Properties props = System.getProperties(); Session session = Session.getDefaultInstance(props, null); Address fromUser = new InternetAddress("\"Eric H. Echidna\"<eric@bouncycastle.org>"); Address toUser = new InternetAddress("example@bouncycastle.org"); MimeMessage body = new MimeMessage(session); body.setFrom(fromUser); body.setRecipient(Message.RecipientType.TO, toUser); body.setSubject("example signed message"); body.setContent(res.getContent(), res.getContentType()); body.saveChanges(); Assert.assertTrue(toolkit.isValidSignature(body, new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(_signCert))); } private MimeMultipart generateMultiPartRsa( String algorithm, MimeBodyPart msg, Map micalgs) throws Exception { List certList = new ArrayList(); certList.add(_signCert); certList.add(_origCert); Store certs = new JcaCertStore(certList); SMIMESignedGenerator gen = new SMIMESignedGenerator(micalgs); gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build(algorithm, _signKP.getPrivate(), _signCert)); gen.addCertificates(certs); return gen.generate(msg); } private MimeMessage makeMimeMessage(MimeBodyPart res) throws MessagingException, IOException { Properties props = System.getProperties(); Session session = Session.getDefaultInstance(props, null); Address fromUser = new InternetAddress("\"Eric H. Echidna\"<eric@bouncycastle.org>"); Address toUser = new InternetAddress("example@bouncycastle.org"); MimeMessage body = new MimeMessage(session); body.setFrom(fromUser); body.setRecipient(Message.RecipientType.TO, toUser); body.setSubject("example message"); body.setContent(res.getContent(), res.getContentType()); body.saveChanges(); return body; } private MimeMessage makeMimeMessage(MimeMultipart mm) throws MessagingException, IOException { Properties props = System.getProperties(); Session session = Session.getDefaultInstance(props, null); Address fromUser = new InternetAddress("\"Eric H. Echidna\"<eric@bouncycastle.org>"); Address toUser = new InternetAddress("example@bouncycastle.org"); MimeMessage body = new MimeMessage(session); body.setFrom(fromUser); body.setRecipient(Message.RecipientType.TO, toUser); body.setSubject("example message"); body.setContent(mm, mm.getContentType()); body.saveChanges(); return body; } private MimeBodyPart generateEncapsulated() throws CertificateEncodingException, OperatorCreationException, SMIMEException { List certList = new ArrayList(); certList.add(_signCert); certList.add(_origCert); Store certs = new JcaCertStore(certList); SMIMESignedGenerator gen = new SMIMESignedGenerator(); gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider(BC).build("SHA1withRSA", _signKP.getPrivate(), _signCert)); gen.addCertificates(certs); return gen.generateEncapsulated(msg); } private JcaPKIXIdentity openIdentityResource( String keyFileName, String certFileName) throws IOException, CertificateException { InputStream keyRes = this.getClass().getResourceAsStream(keyFileName); InputStream certRes = this.getClass().getResourceAsStream(certFileName); return new JcaPKIXIdentityBuilder().setProvider(BC).build(keyRes, certRes); } public static void main(String args[]) { junit.textui.TestRunner.run(SMIMEToolkitTest.class); } public static Test suite() { return new SMIMETestSetup(new TestSuite(SMIMEToolkitTest.class)); } }