diff options
Diffstat (limited to 'mail/src/test/java/org/spongycastle/mail/smime/test/SMIMEMiscTest.java')
-rw-r--r-- | mail/src/test/java/org/spongycastle/mail/smime/test/SMIMEMiscTest.java | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/mail/src/test/java/org/spongycastle/mail/smime/test/SMIMEMiscTest.java b/mail/src/test/java/org/spongycastle/mail/smime/test/SMIMEMiscTest.java new file mode 100644 index 00000000..690c89cc --- /dev/null +++ b/mail/src/test/java/org/spongycastle/mail/smime/test/SMIMEMiscTest.java @@ -0,0 +1,367 @@ +package org.bouncycastle.mail.smime.test; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.security.KeyPair; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +import javax.mail.Address; +import javax.mail.Message; +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.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute; +import org.bouncycastle.asn1.smime.SMIMECapability; +import org.bouncycastle.asn1.smime.SMIMECapabilityVector; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaCertStore; +import org.bouncycastle.cms.CMSAlgorithm; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.RecipientInformation; +import org.bouncycastle.cms.SignerInformation; +import org.bouncycastle.cms.SignerInformationStore; +import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder; +import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter; +import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder; +import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; +import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; +import org.bouncycastle.cms.jcajce.ZlibCompressor; +import org.bouncycastle.cms.test.CMSTestUtil; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.mail.smime.SMIMECompressedGenerator; +import org.bouncycastle.mail.smime.SMIMEEnveloped; +import org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator; +import org.bouncycastle.mail.smime.SMIMESigned; +import org.bouncycastle.mail.smime.SMIMESignedGenerator; +import org.bouncycastle.mail.smime.SMIMESignedParser; +import org.bouncycastle.mail.smime.SMIMEUtil; +import org.bouncycastle.mail.smime.util.FileBackedMimeBodyPart; +import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.bouncycastle.util.Store; + +public class SMIMEMiscTest + extends TestCase +{ + static MimeBodyPart msg; + + static String signDN; + static KeyPair signKP; + static X509Certificate signCert; + + static String origDN; + static KeyPair origKP; + static X509Certificate origCert; + + static String reciDN; + static KeyPair reciKP; + static X509Certificate reciCert; + + private static final JcaX509CertSelectorConverter selectorConverter = new JcaX509CertSelectorConverter(); + + KeyPair dsaSignKP; + X509Certificate dsaSignCert; + + KeyPair dsaOrigKP; + X509Certificate dsaOrigCert; + + static + { + try + { + msg = SMIMETestUtil.makeMimeBodyPart("Hello world!\n"); + + signDN = "O=Bouncy Castle, C=AU"; + signKP = CMSTestUtil.makeKeyPair(); + signCert = CMSTestUtil.makeCertificate(signKP, signDN, signKP, signDN); + + origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; + origKP = CMSTestUtil.makeKeyPair(); + origCert = CMSTestUtil.makeCertificate(origKP, origDN, signKP, signDN); + } + catch (Exception e) + { + throw new RuntimeException("problem setting up signed test class: " + e); + } + } + + /* + * + * INFRASTRUCTURE + * + */ + + public SMIMEMiscTest(String name) + { + super(name); + } + + public static void main(String args[]) + { + Security.addProvider(new BouncyCastleProvider()); + + junit.textui.TestRunner.run(SMIMEMiscTest.class); + } + + public static Test suite() + { + return new SMIMETestSetup(new TestSuite(SMIMEMiscTest.class)); + } + + public void testSHA256WithRSAParserEncryptedWithAES() + throws Exception + { + List certList = new ArrayList(); + + certList.add(origCert); + certList.add(signCert); + + Store certs = new JcaCertStore(certList); + + SMIMEEnvelopedGenerator encGen = new SMIMEEnvelopedGenerator(); + + encGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(origCert).setProvider("BC")); + + MimeBodyPart mp = encGen.generate(msg, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider("BC").build()); + ASN1EncodableVector signedAttrs = generateSignedAttributes(); + + SMIMESignedGenerator gen = new SMIMESignedGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setSignedAttributeGenerator(new AttributeTable(signedAttrs)).build("SHA256withRSA", origKP.getPrivate(), origCert)); + gen.addCertificates(certs); + + MimeMultipart smm = gen.generate(mp); + File tmpFile = File.createTempFile("bcTest", ".mime"); + + MimeMessage msg = createMimeMessage(tmpFile, smm); + + SMIMESignedParser s = new SMIMESignedParser(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build(), (MimeMultipart)msg.getContent()); + + certs = s.getCertificates(); + + verifyMessageBytes(mp, s.getContent()); + + verifySigners(certs, s.getSignerInfos()); + + tmpFile.delete(); + } + + public void testSHA256WithRSACompressed() + throws Exception + { + List certList = new ArrayList(); + + certList.add(origCert); + certList.add(signCert); + + Store certs = new JcaCertStore(certList); + + SMIMECompressedGenerator cGen = new SMIMECompressedGenerator(); + + MimeBodyPart mp = cGen.generate(msg, new ZlibCompressor()); + + ASN1EncodableVector signedAttrs = generateSignedAttributes(); + + SMIMESignedGenerator gen = new SMIMESignedGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setSignedAttributeGenerator(new AttributeTable(signedAttrs)).build("SHA256withRSA", origKP.getPrivate(), origCert)); + gen.addCertificates(certs); + + MimeMultipart smm = gen.generate(mp); + File tmpFile = File.createTempFile("bcTest", ".mime"); + + MimeMessage msg = createMimeMessage(tmpFile, smm); + + SMIMESigned s = new SMIMESigned((MimeMultipart)msg.getContent()); + + certs = s.getCertificates(); + + verifyMessageBytes(mp, s.getContent()); + + verifySigners(certs, s.getSignerInfos()); + + tmpFile.delete(); + } + + public void testQuotePrintableSigPreservation() + throws Exception + { + MimeMessage msg = new MimeMessage((Session)null, getClass().getResourceAsStream("qp-soft-break.eml")); + + SMIMEEnvelopedGenerator encGen = new SMIMEEnvelopedGenerator(); + + encGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(origCert).setProvider("BC")); + + MimeBodyPart mp = encGen.generate(msg, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider("BC").build()); + + SMIMEEnveloped env = new SMIMEEnveloped(mp); + RecipientInformation ri = (RecipientInformation)env.getRecipientInfos().getRecipients().iterator().next(); + MimeBodyPart mm = SMIMEUtil.toMimeBodyPart(ri.getContentStream(new JceKeyTransEnvelopedRecipient(origKP.getPrivate()).setProvider("BC"))); + SMIMESigned s = new SMIMESigned((MimeMultipart)mm.getContent()); + Collection c = s.getSignerInfos().getSigners(); + Iterator it = c.iterator(); + Store certs = s.getCertificates(); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert))); + } + + ((FileBackedMimeBodyPart)mm).dispose(); + } + + public void testSHA256WithRSAParserCompressed() + throws Exception + { + List certList = new ArrayList(); + + certList.add(origCert); + certList.add(signCert); + + Store certs = new JcaCertStore(certList); + + SMIMECompressedGenerator cGen = new SMIMECompressedGenerator(); + + MimeBodyPart mp = cGen.generate(msg, new ZlibCompressor()); + + ASN1EncodableVector signedAttrs = generateSignedAttributes(); + + SMIMESignedGenerator gen = new SMIMESignedGenerator(); + + gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setSignedAttributeGenerator(new AttributeTable(signedAttrs)).build("SHA256withRSA", origKP.getPrivate(), origCert)); + gen.addCertificates(certs); + + MimeMultipart smm = gen.generate(mp); + File tmpFile = File.createTempFile("bcTest", ".mime"); + + MimeMessage msg = createMimeMessage(tmpFile, smm); + + SMIMESignedParser s = new SMIMESignedParser(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build(), (MimeMultipart)msg.getContent()); + + certs = s.getCertificates(); + + verifyMessageBytes(mp, s.getContent()); + + verifySigners(certs, s.getSignerInfos()); + + tmpFile.delete(); + } + + public void testBrokenEnvelope() + throws Exception + { + Session session = Session.getDefaultInstance(System.getProperties(), null); + MimeMessage msg = new MimeMessage(session, getClass().getResourceAsStream("brokenEnv.message")); + + try + { + new SMIMEEnveloped(msg); + } + catch (CMSException e) + { + if (!e.getMessage().equals("Malformed content.")) + { + fail("wrong exception on bogus envelope"); + } + } + } + + private void verifySigners(Store certs, SignerInformationStore signers) + throws Exception + { + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert))); + } + } + + private void verifyMessageBytes(MimeBodyPart a, MimeBodyPart b) + throws Exception + { + ByteArrayOutputStream bOut1 = new ByteArrayOutputStream(); + + a.writeTo(bOut1); + bOut1.close(); + + ByteArrayOutputStream bOut2 = new ByteArrayOutputStream(); + + b.writeTo(bOut2); + bOut2.close(); + + assertEquals(true, Arrays.equals(bOut1.toByteArray(), bOut2.toByteArray())); + } + + /** + * Create a mime message representing the multipart. We need to do + * this as otherwise no raw content stream for the message will exist. + */ + private MimeMessage createMimeMessage(File tmpFile, MimeMultipart smm) + throws Exception + { + FileOutputStream fOut = new FileOutputStream(tmpFile); + 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(); + + body.writeTo(fOut); + + fOut.close(); + + return new MimeMessage(session, new FileInputStream(tmpFile)); + } + + private ASN1EncodableVector generateSignedAttributes() + { + ASN1EncodableVector signedAttrs = new ASN1EncodableVector(); + SMIMECapabilityVector caps = new SMIMECapabilityVector(); + + caps.addCapability(SMIMECapability.dES_EDE3_CBC); + caps.addCapability(SMIMECapability.rC2_CBC, 128); + caps.addCapability(SMIMECapability.dES_CBC); + + signedAttrs.add(new SMIMECapabilitiesAttribute(caps)); + + return signedAttrs; + } +} |