Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mail/src/main/java/org/spongycastle/mail/smime/examples')
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/CreateCompressedMail.java57
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/CreateEncryptedMail.java128
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeCompressedMail.java63
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeEncryptedMail.java105
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeSignedMail.java198
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/CreateSignedMail.java221
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/CreateSignedMultipartMail.java213
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/ExampleUtils.java77
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/ReadCompressedMail.java41
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/ReadEncryptedMail.java94
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeCompressedMail.java38
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeEncryptedMail.java71
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeSignedMail.java125
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/ReadSignedMail.java176
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/SendSignedAndEncryptedMail.java192
-rw-r--r--mail/src/main/java/org/spongycastle/mail/smime/examples/ValidateSignedMail.java352
16 files changed, 2151 insertions, 0 deletions
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateCompressedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateCompressedMail.java
new file mode 100644
index 00000000..5d1df695
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateCompressedMail.java
@@ -0,0 +1,57 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.FileOutputStream;
+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 org.bouncycastle.cms.jcajce.ZlibCompressor;
+import org.bouncycastle.mail.smime.SMIMECompressedGenerator;
+
+/**
+ * a simple example that creates a single compressed mail message.
+ */
+public class CreateCompressedMail
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ //
+ // create the generator for creating an smime/compressed message
+ //
+ SMIMECompressedGenerator gen = new SMIMECompressedGenerator();
+
+ //
+ // create the base for our message
+ //
+ MimeBodyPart msg = new MimeBodyPart();
+
+ msg.setText("Hello world!");
+
+ MimeBodyPart mp = gen.generate(msg, new ZlibCompressor());
+
+ //
+ // Get a Session object and create the mail message
+ //
+ 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 compressed message");
+ body.setContent(mp.getContent(), mp.getContentType());
+ body.saveChanges();
+
+ body.writeTo(new FileOutputStream("compressed.message"));
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateEncryptedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateEncryptedMail.java
new file mode 100644
index 00000000..6ef42d9d
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateEncryptedMail.java
@@ -0,0 +1,128 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.security.KeyStore;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+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 org.bouncycastle.cms.CMSAlgorithm;
+import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
+import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator;
+
+/**
+ * a simple example that creates a single encrypted mail message.
+ * <p>
+ * The key store can be created using the class in
+ * org.bouncycastle.jce.examples.PKCS12Example - the program expects only one
+ * key to be present in the key file.
+ * <p>
+ * Note: while this means that both the private key is available to
+ * the program, the private key is retrieved from the keystore only for
+ * the purposes of locating the corresponding public key, in normal circumstances
+ * you would only be doing this with a certificate available.
+ */
+public class CreateEncryptedMail
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ if (args.length != 2)
+ {
+ System.err.println("usage: CreateEncryptedMail pkcs12Keystore password");
+ System.exit(0);
+ }
+
+ if (Security.getProvider("BC") == null)
+ {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
+ //
+ // Open the key store
+ //
+ KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
+
+ ks.load(new FileInputStream(args[0]), args[1].toCharArray());
+
+ Enumeration e = ks.aliases();
+ String keyAlias = null;
+
+ while (e.hasMoreElements())
+ {
+ String alias = (String)e.nextElement();
+
+ if (ks.isKeyEntry(alias))
+ {
+ keyAlias = alias;
+ }
+ }
+
+ if (keyAlias == null)
+ {
+ System.err.println("can't find a private key!");
+ System.exit(0);
+ }
+
+ Certificate[] chain = ks.getCertificateChain(keyAlias);
+
+ //
+ // create the generator for creating an smime/encrypted message
+ //
+ SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();
+
+ gen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator((X509Certificate)chain[0]).setProvider("BC"));
+
+ //
+ // create a subject key id - this has to be done the same way as
+ // it is done in the certificate associated with the private key
+ // version 3 only.
+ //
+ /*
+ MessageDigest dig = MessageDigest.getInstance("SHA1", "BC");
+
+ dig.update(cert.getPublicKey().getEncoded());
+
+ gen.addKeyTransRecipient(cert.getPublicKey(), dig.digest());
+ */
+
+ //
+ // create the base for our message
+ //
+ MimeBodyPart msg = new MimeBodyPart();
+
+ msg.setText("Hello world!");
+
+ MimeBodyPart mp = gen.generate(msg, new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC).setProvider("BC").build());
+ //
+ // Get a Session object and create the mail message
+ //
+ 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 encrypted message");
+ body.setContent(mp.getContent(), mp.getContentType());
+ body.saveChanges();
+
+ body.writeTo(new FileOutputStream("encrypted.message"));
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeCompressedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeCompressedMail.java
new file mode 100644
index 00000000..63c5125d
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeCompressedMail.java
@@ -0,0 +1,63 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Properties;
+
+import javax.activation.DataHandler;
+import javax.activation.FileDataSource;
+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 org.bouncycastle.cms.jcajce.ZlibCompressor;
+import org.bouncycastle.mail.smime.SMIMECompressedGenerator;
+
+/**
+ * a simple example that creates a single compressed mail message using the large
+ * file model.
+ */
+public class CreateLargeCompressedMail
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ //
+ // create the generator for creating an smime/compressed message
+ //
+ SMIMECompressedGenerator gen = new SMIMECompressedGenerator();
+
+ //
+ // create the base for our message
+ //
+ MimeBodyPart msg = new MimeBodyPart();
+
+ msg.setDataHandler(new DataHandler(new FileDataSource(new File(args[0]))));
+ msg.setHeader("Content-Type", "application/octet-stream");
+ msg.setHeader("Content-Transfer-Encoding", "binary");
+
+ MimeBodyPart mp = gen.generate(msg, new ZlibCompressor());
+
+ //
+ // Get a Session object and create the mail message
+ //
+ 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 compressed message");
+ body.setContent(mp.getContent(), mp.getContentType());
+ body.saveChanges();
+
+ body.writeTo(new FileOutputStream("compressed.message"));
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeEncryptedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeEncryptedMail.java
new file mode 100644
index 00000000..5fc7663a
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeEncryptedMail.java
@@ -0,0 +1,105 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import javax.activation.DataHandler;
+import javax.activation.FileDataSource;
+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 org.bouncycastle.cms.CMSAlgorithm;
+import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
+import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
+import org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator;
+
+/**
+ * a simple example that creates a single encrypted mail message.
+ * <p>
+ * The key store can be created using the class in
+ * org.bouncycastle.jce.examples.PKCS12Example - the program expects only one
+ * key to be present in the key file.
+ * <p>
+ * Note: while this means that both the private key is available to
+ * the program, the private key is retrieved from the keystore only for
+ * the purposes of locating the corresponding public key, in normal circumstances
+ * you would only be doing this with a certificate available.
+ */
+public class CreateLargeEncryptedMail
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ if (args.length != 3)
+ {
+ System.err.println("usage: CreateLargeEncryptedMail pkcs12Keystore password inputFile");
+ System.exit(0);
+ }
+
+ //
+ // Open the key store
+ //
+ KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
+ String keyAlias = ExampleUtils.findKeyAlias(ks, args[0], args[1].toCharArray());
+
+ Certificate[] chain = ks.getCertificateChain(keyAlias);
+
+ //
+ // create the generator for creating an smime/encrypted message
+ //
+ SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();
+
+ gen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator((X509Certificate)chain[0]).setProvider("BC"));
+
+ //
+ // create a subject key id - this has to be done the same way as
+ // it is done in the certificate associated with the private key
+ // version 3 only.
+ //
+ /*
+ MessageDigest dig = MessageDigest.getInstance("SHA1", "BC");
+
+ dig.update(cert.getPublicKey().getEncoded());
+
+ gen.addKeyTransRecipient(cert.getPublicKey(), dig.digest());
+ */
+
+ //
+ // create the base for our message
+ //
+ MimeBodyPart msg = new MimeBodyPart();
+
+ msg.setDataHandler(new DataHandler(new FileDataSource(new File(args[2]))));
+ msg.setHeader("Content-Type", "application/octet-stream");
+ msg.setHeader("Content-Transfer-Encoding", "binary");
+
+ MimeBodyPart mp = gen.generate(msg, new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC).setProvider("BC").build());
+
+ //
+ // Get a Session object and create the mail message
+ //
+ 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 encrypted message");
+ body.setContent(mp.getContent(), mp.getContentType());
+ body.saveChanges();
+
+ body.writeTo(new FileOutputStream("encrypted.message"));
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeSignedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeSignedMail.java
new file mode 100644
index 00000000..ffb092ab
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateLargeSignedMail.java
@@ -0,0 +1,198 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+
+import javax.activation.DataHandler;
+import javax.activation.FileDataSource;
+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 org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.cms.AttributeTable;
+import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
+import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
+import org.bouncycastle.asn1.smime.SMIMECapability;
+import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
+import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.X509Extension;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaCertStore;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
+import org.bouncycastle.mail.smime.SMIMESignedGenerator;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.util.Store;
+
+/**
+ * a simple example that creates a single signed mail message.
+ */
+public class CreateLargeSignedMail
+{
+ //
+ // certificate serial number seed.
+ //
+ static int serialNo = 1;
+
+ /**
+ * create a basic X509 certificate from the given keys
+ */
+ static X509Certificate makeCertificate(
+ KeyPair subKP,
+ String subDN,
+ KeyPair issKP,
+ String issDN)
+ throws GeneralSecurityException, IOException, OperatorCreationException
+ {
+ PublicKey subPub = subKP.getPublic();
+ PrivateKey issPriv = issKP.getPrivate();
+ PublicKey issPub = issKP.getPublic();
+
+ JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
+ X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder(new X500Name(issDN), BigInteger.valueOf(serialNo++), new Date(System.currentTimeMillis()), new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)), new X500Name(subDN), subPub);
+
+ v3CertGen.addExtension(
+ X509Extension.subjectKeyIdentifier,
+ false,
+ extUtils.createSubjectKeyIdentifier(subPub));
+
+ v3CertGen.addExtension(
+ X509Extension.authorityKeyIdentifier,
+ false,
+ extUtils.createAuthorityKeyIdentifier(issPub));
+
+ return new JcaX509CertificateConverter().setProvider("BC").getCertificate(v3CertGen.build(new JcaContentSignerBuilder("MD5withRSA").setProvider("BC").build(issPriv)));
+ }
+
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ //
+ // set up our certs
+ //
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
+
+ kpg.initialize(1024, new SecureRandom());
+
+ //
+ // cert that issued the signing certificate
+ //
+ String signDN = "O=Bouncy Castle, C=AU";
+ KeyPair signKP = kpg.generateKeyPair();
+ X509Certificate signCert = makeCertificate(
+ signKP, signDN, signKP, signDN);
+
+ //
+ // cert we sign against
+ //
+ String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU";
+ KeyPair origKP = kpg.generateKeyPair();
+ X509Certificate origCert = makeCertificate(
+ origKP, origDN, signKP, signDN);
+
+ List certList = new ArrayList();
+
+ certList.add(origCert);
+ certList.add(signCert);
+
+ //
+ // create a CertStore containing the certificates we want carried
+ // in the signature
+ //
+ Store certs = new JcaCertStore(certList);
+
+ //
+ // create some smime capabilities in case someone wants to respond
+ //
+ 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));
+
+ //
+ // add an encryption key preference for encrypted responses -
+ // normally this would be different from the signing certificate...
+ //
+ IssuerAndSerialNumber issAndSer = new IssuerAndSerialNumber(
+ new X500Name(signDN), origCert.getSerialNumber());
+
+ signedAttrs.add(new SMIMEEncryptionKeyPreferenceAttribute(issAndSer));
+
+ //
+ // create the generator for creating an smime/signed message
+ //
+ SMIMESignedGenerator gen = new SMIMESignedGenerator();
+
+ //
+ // add a signer to the generator - this specifies we are using SHA1 and
+ // adding the smime attributes above to the signed attributes that
+ // will be generated as part of the signature. The encryption algorithm
+ // used is taken from the key - in this RSA with PKCS1Padding
+ //
+ gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setSignedAttributeGenerator(new AttributeTable(signedAttrs)).build("SHA1withRSA", origKP.getPrivate(), origCert));
+
+ //
+ // add our pool of certs and cerls (if any) to go with the signature
+ //
+ gen.addCertificates(certs);
+
+ //
+ // create the base for our message
+ //
+ MimeBodyPart msg = new MimeBodyPart();
+
+ msg.setDataHandler(new DataHandler(new FileDataSource(new File(args[0]))));
+ msg.setHeader("Content-Type", "application/octet-stream");
+ msg.setHeader("Content-Transfer-Encoding", "base64");
+
+ //
+ // extract the multipart object from the SMIMESigned object.
+ //
+ MimeMultipart mm = gen.generate(msg);
+
+ //
+ // Get a Session object and create the mail message
+ //
+ 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(mm, mm.getContentType());
+ body.saveChanges();
+
+ body.writeTo(new FileOutputStream("signed.message"));
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateSignedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateSignedMail.java
new file mode 100644
index 00000000..8f3fb787
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateSignedMail.java
@@ -0,0 +1,221 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+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 org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.cms.AttributeTable;
+import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
+import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
+import org.bouncycastle.asn1.smime.SMIMECapability;
+import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
+import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.asn1.x509.X509Extension;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.bc.BcX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaCertStore;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
+import org.bouncycastle.mail.smime.SMIMESignedGenerator;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.util.Store;
+
+/**
+ * a simple example that creates a single signed mail message.
+ */
+public class CreateSignedMail
+{
+ //
+ // certificate serial number seed.
+ //
+ static int serialNo = 1;
+
+ static AuthorityKeyIdentifier createAuthorityKeyId(
+ PublicKey pub)
+ throws IOException
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(pub.getEncoded());
+ SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+ (ASN1Sequence)new ASN1InputStream(bIn).readObject());
+
+ return new AuthorityKeyIdentifier(info);
+ }
+
+ static SubjectKeyIdentifier createSubjectKeyId(
+ PublicKey pub)
+ throws IOException
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(pub.getEncoded());
+
+ SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+ (ASN1Sequence)new ASN1InputStream(bIn).readObject());
+
+ return new BcX509ExtensionUtils().createSubjectKeyIdentifier(info);
+ }
+
+ /**
+ * create a basic X509 certificate from the given keys
+ */
+ static X509Certificate makeCertificate(
+ KeyPair subKP,
+ String subDN,
+ KeyPair issKP,
+ String issDN)
+ throws GeneralSecurityException, IOException, OperatorCreationException
+ {
+ PublicKey subPub = subKP.getPublic();
+ PrivateKey issPriv = issKP.getPrivate();
+ PublicKey issPub = issKP.getPublic();
+
+ X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder(new X500Name(issDN), BigInteger.valueOf(serialNo++), new Date(System.currentTimeMillis()), new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)), new X500Name(subDN), subPub);
+
+ v3CertGen.addExtension(
+ X509Extension.subjectKeyIdentifier,
+ false,
+ createSubjectKeyId(subPub));
+
+ v3CertGen.addExtension(
+ X509Extension.authorityKeyIdentifier,
+ false,
+ createAuthorityKeyId(issPub));
+
+ return new JcaX509CertificateConverter().setProvider("BC").getCertificate(v3CertGen.build(new JcaContentSignerBuilder("MD5withRSA").setProvider("BC").build(issPriv)));
+ }
+
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ //
+ // set up our certs
+ //
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
+
+ kpg.initialize(1024, new SecureRandom());
+
+ //
+ // cert that issued the signing certificate
+ //
+ String signDN = "O=Bouncy Castle, C=AU";
+ KeyPair signKP = kpg.generateKeyPair();
+ X509Certificate signCert = makeCertificate(
+ signKP, signDN, signKP, signDN);
+
+ //
+ // cert we sign against
+ //
+ String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU";
+ KeyPair origKP = kpg.generateKeyPair();
+ X509Certificate origCert = makeCertificate(
+ origKP, origDN, signKP, signDN);
+
+ List certList = new ArrayList();
+
+ certList.add(origCert);
+ certList.add(signCert);
+
+ //
+ // create a CertStore containing the certificates we want carried
+ // in the signature
+ //
+ Store certs = new JcaCertStore(certList);
+
+ //
+ // create some smime capabilities in case someone wants to respond
+ //
+ 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));
+
+ //
+ // add an encryption key preference for encrypted responses -
+ // normally this would be different from the signing certificate...
+ //
+ IssuerAndSerialNumber issAndSer = new IssuerAndSerialNumber(
+ new X500Name(signDN), origCert.getSerialNumber());
+
+ signedAttrs.add(new SMIMEEncryptionKeyPreferenceAttribute(issAndSer));
+
+ //
+ // create the generator for creating an smime/signed message
+ //
+ SMIMESignedGenerator gen = new SMIMESignedGenerator();
+
+ //
+ // add a signer to the generator - this specifies we are using SHA1 and
+ // adding the smime attributes above to the signed attributes that
+ // will be generated as part of the signature. The encryption algorithm
+ // used is taken from the key - in this RSA with PKCS1Padding
+ //
+ gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setSignedAttributeGenerator(new AttributeTable(signedAttrs)).build("SHA1withRSA", origKP.getPrivate(), origCert));
+
+ //
+ // add our pool of certs and cerls (if any) to go with the signature
+ //
+ gen.addCertificates(certs);
+
+ //
+ // create the base for our message
+ //
+ MimeBodyPart msg = new MimeBodyPart();
+
+ msg.setText("Hello world!");
+
+ //
+ // extract the multipart object from the SMIMESigned object.
+ //
+ MimeMultipart mm = gen.generate(msg);
+
+ //
+ // Get a Session object and create the mail message
+ //
+ 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(mm, mm.getContentType());
+ body.saveChanges();
+
+ body.writeTo(new FileOutputStream("signed.message"));
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateSignedMultipartMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateSignedMultipartMail.java
new file mode 100644
index 00000000..20d1b3ea
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/CreateSignedMultipartMail.java
@@ -0,0 +1,213 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+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 org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.cms.AttributeTable;
+import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
+import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
+import org.bouncycastle.asn1.smime.SMIMECapability;
+import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
+import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.X509Extension;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaCertStore;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
+import org.bouncycastle.mail.smime.SMIMESignedGenerator;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.util.Store;
+
+/**
+ * a simple example that creates a single signed multipart mail message.
+ */
+public class CreateSignedMultipartMail
+{
+ //
+ // certificate serial number seed.
+ //
+ static int serialNo = 1;
+
+ /**
+ * create a basic X509 certificate from the given keys
+ */
+ static X509Certificate makeCertificate(
+ KeyPair subKP,
+ String subDN,
+ KeyPair issKP,
+ String issDN)
+ throws GeneralSecurityException, IOException, OperatorCreationException
+ {
+ PublicKey subPub = subKP.getPublic();
+ PrivateKey issPriv = issKP.getPrivate();
+ PublicKey issPub = issKP.getPublic();
+
+ JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
+ X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder(new X500Name(issDN), BigInteger.valueOf(serialNo++), new Date(System.currentTimeMillis()), new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)), new X500Name(subDN), subPub);
+
+ v3CertGen.addExtension(
+ X509Extension.subjectKeyIdentifier,
+ false,
+ extUtils.createSubjectKeyIdentifier(subPub));
+
+ v3CertGen.addExtension(
+ X509Extension.authorityKeyIdentifier,
+ false,
+ extUtils.createAuthorityKeyIdentifier(issPub));
+
+ return new JcaX509CertificateConverter().setProvider("BC").getCertificate(v3CertGen.build(new JcaContentSignerBuilder("MD5withRSA").setProvider("BC").build(issPriv)));
+ }
+
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ //
+ // set up our certs
+ //
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
+
+ kpg.initialize(1024, new SecureRandom());
+
+ //
+ // cert that issued the signing certificate
+ //
+ String signDN = "O=Bouncy Castle, C=AU";
+ KeyPair signKP = kpg.generateKeyPair();
+ X509Certificate signCert = makeCertificate(
+ signKP, signDN, signKP, signDN);
+
+ //
+ // cert we sign against
+ //
+ String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU";
+ KeyPair origKP = kpg.generateKeyPair();
+ X509Certificate origCert = makeCertificate(
+ origKP, origDN, signKP, signDN);
+
+ List certList = new ArrayList();
+
+ certList.add(origCert);
+ certList.add(signCert);
+
+ //
+ // create a CertStore containing the certificates we want carried
+ // in the signature
+ //
+ Store certs = new JcaCertStore(certList);
+
+ //
+ // create some smime capabilities in case someone wants to respond
+ //
+ 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));
+
+ //
+ // add an encryption key preference for encrypted responses -
+ // normally this would be different from the signing certificate...
+ //
+ IssuerAndSerialNumber issAndSer = new IssuerAndSerialNumber(
+ new X500Name(signDN), origCert.getSerialNumber());
+
+ signedAttrs.add(new SMIMEEncryptionKeyPreferenceAttribute(issAndSer));
+
+ //
+ // create the generator for creating an smime/signed message
+ //
+ SMIMESignedGenerator gen = new SMIMESignedGenerator();
+
+ //
+ // add a signer to the generator - this specifies we are using SHA1 and
+ // adding the smime attributes above to the signed attributes that
+ // will be generated as part of the signature. The encryption algorithm
+ // used is taken from the key - in this RSA with PKCS1Padding
+ //
+ gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setSignedAttributeGenerator(new AttributeTable(signedAttrs)).build("SHA1withRSA", origKP.getPrivate(), origCert));
+
+ //
+ // add our pool of certs and cerls (if any) to go with the signature
+ //
+ gen.addCertificates(certs);
+
+ //
+ // create the base for our message
+ //
+ MimeBodyPart msg1 = new MimeBodyPart();
+
+ msg1.setText("Hello part 1!");
+
+ MimeBodyPart msg2 = new MimeBodyPart();
+
+ msg2.setText("Hello part 2!");
+
+ MimeMultipart mp = new MimeMultipart();
+
+ mp.addBodyPart(msg1);
+ mp.addBodyPart(msg2);
+
+ MimeBodyPart m = new MimeBodyPart();
+
+ //
+ // be careful about setting extra headers here. Some mail clients
+ // ignore the To and From fields (for example) in the body part
+ // that contains the multipart. The result of this will be that the
+ // signature fails to verify... Outlook Express is an example of
+ // a client that exhibits this behaviour.
+ //
+ m.setContent(mp);
+
+ //
+ // extract the multipart object from the SMIMESigned object.
+ //
+ MimeMultipart mm = gen.generate(m);
+
+ //
+ // Get a Session object and create the mail message
+ //
+ 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(mm, mm.getContentType());
+ body.saveChanges();
+
+ body.writeTo(new FileOutputStream("signed.message"));
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/ExampleUtils.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/ExampleUtils.java
new file mode 100644
index 00000000..10c0f06c
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/ExampleUtils.java
@@ -0,0 +1,77 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.KeyStore;
+import java.util.Enumeration;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeBodyPart;
+
+public class ExampleUtils
+{
+ /**
+ * Dump the content of the passed in BodyPart to the file fileName.
+ *
+ * @throws MessagingException
+ * @throws IOException
+ */
+ public static void dumpContent(
+ MimeBodyPart bodyPart,
+ String fileName)
+ throws MessagingException, IOException
+ {
+ //
+ // print mime type of compressed content
+ //
+ System.out.println("content type: " + bodyPart.getContentType());
+
+ //
+ // recover the compressed content
+ //
+ OutputStream out = new FileOutputStream(fileName);
+ InputStream in = bodyPart.getInputStream();
+
+ byte[] buf = new byte[10000];
+ int len;
+
+ while ((len = in.read(buf, 0, buf.length)) > 0)
+ {
+ out.write(buf, 0, len);
+ }
+
+ out.close();
+ }
+
+ public static String findKeyAlias(
+ KeyStore store,
+ String storeName,
+ char[] password)
+ throws Exception
+ {
+ store.load(new FileInputStream(storeName), password);
+
+ Enumeration e = store.aliases();
+ String keyAlias = null;
+
+ while (e.hasMoreElements())
+ {
+ String alias = (String)e.nextElement();
+
+ if (store.isKeyEntry(alias))
+ {
+ keyAlias = alias;
+ }
+ }
+
+ if (keyAlias == null)
+ {
+ throw new IllegalArgumentException("can't find a private key in keyStore: " + storeName);
+ }
+
+ return keyAlias;
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadCompressedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadCompressedMail.java
new file mode 100644
index 00000000..b462b336
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadCompressedMail.java
@@ -0,0 +1,41 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.FileInputStream;
+import java.util.Properties;
+
+import javax.mail.Session;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+
+import org.bouncycastle.cms.jcajce.ZlibExpanderProvider;
+import org.bouncycastle.mail.smime.SMIMECompressed;
+import org.bouncycastle.mail.smime.SMIMEUtil;
+
+/**
+ * a simple example that reads a compressed email.
+ * <p>
+ */
+public class ReadCompressedMail
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ //
+ // Get a Session object with the default properties.
+ //
+ Properties props = System.getProperties();
+
+ Session session = Session.getDefaultInstance(props, null);
+
+ MimeMessage msg = new MimeMessage(session, new FileInputStream("compressed.message"));
+
+ SMIMECompressed m = new SMIMECompressed(msg);
+
+ MimeBodyPart res = SMIMEUtil.toMimeBodyPart(m.getContent(new ZlibExpanderProvider()));
+
+ System.out.println("Message Contents");
+ System.out.println("----------------");
+ System.out.println(res.getContent());
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadEncryptedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadEncryptedMail.java
new file mode 100644
index 00000000..a180994f
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadEncryptedMail.java
@@ -0,0 +1,94 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import javax.mail.Session;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+
+import org.bouncycastle.cms.RecipientId;
+import org.bouncycastle.cms.RecipientInformation;
+import org.bouncycastle.cms.RecipientInformationStore;
+import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
+import org.bouncycastle.cms.jcajce.JceKeyTransRecipientId;
+import org.bouncycastle.mail.smime.SMIMEEnveloped;
+import org.bouncycastle.mail.smime.SMIMEUtil;
+
+/**
+ * a simple example that reads an encrypted email.
+ * <p>
+ * The key store can be created using the class in
+ * org.bouncycastle.jce.examples.PKCS12Example - the program expects only one
+ * key to be present.
+ */
+public class ReadEncryptedMail
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ if (args.length != 2)
+ {
+ System.err.println("usage: ReadEncryptedMail pkcs12Keystore password");
+ System.exit(0);
+ }
+
+ //
+ // Open the key store
+ //
+ KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
+
+ ks.load(new FileInputStream(args[0]), args[1].toCharArray());
+
+ Enumeration e = ks.aliases();
+ String keyAlias = null;
+
+ while (e.hasMoreElements())
+ {
+ String alias = (String)e.nextElement();
+
+ if (ks.isKeyEntry(alias))
+ {
+ keyAlias = alias;
+ }
+ }
+
+ if (keyAlias == null)
+ {
+ System.err.println("can't find a private key!");
+ System.exit(0);
+ }
+
+ //
+ // find the certificate for the private key and generate a
+ // suitable recipient identifier.
+ //
+ X509Certificate cert = (X509Certificate)ks.getCertificate(keyAlias);
+ RecipientId recId = new JceKeyTransRecipientId(cert);
+
+ //
+ // Get a Session object with the default properties.
+ //
+ Properties props = System.getProperties();
+
+ Session session = Session.getDefaultInstance(props, null);
+
+ MimeMessage msg = new MimeMessage(session, new FileInputStream("encrypted.message"));
+
+ SMIMEEnveloped m = new SMIMEEnveloped(msg);
+
+ RecipientInformationStore recipients = m.getRecipientInfos();
+ RecipientInformation recipient = recipients.get(recId);
+
+ MimeBodyPart res = SMIMEUtil.toMimeBodyPart(recipient.getContent(new JceKeyTransEnvelopedRecipient((PrivateKey)ks.getKey(keyAlias, null)).setProvider("BC")));
+
+ System.out.println("Message Contents");
+ System.out.println("----------------");
+ System.out.println(res.getContent());
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeCompressedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeCompressedMail.java
new file mode 100644
index 00000000..795d0497
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeCompressedMail.java
@@ -0,0 +1,38 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.util.Properties;
+
+import javax.mail.Session;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+
+import org.bouncycastle.cms.jcajce.ZlibExpanderProvider;
+import org.bouncycastle.mail.smime.SMIMECompressedParser;
+import org.bouncycastle.mail.smime.SMIMEUtil;
+import org.bouncycastle.mail.smime.util.SharedFileInputStream;
+
+/**
+ * a simple example that reads an oversize compressed email and writes data contained
+ * in the compressed part into a file.
+ */
+public class ReadLargeCompressedMail
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ //
+ // Get a Session object with the default properties.
+ //
+ Properties props = System.getProperties();
+
+ Session session = Session.getDefaultInstance(props, null);
+
+ MimeMessage msg = new MimeMessage(session, new SharedFileInputStream("compressed.message"));
+
+ SMIMECompressedParser m = new SMIMECompressedParser(msg);
+ MimeBodyPart res = SMIMEUtil.toMimeBodyPart(m.getContent(new ZlibExpanderProvider()));
+
+ ExampleUtils.dumpContent(res, args[0]);
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeEncryptedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeEncryptedMail.java
new file mode 100644
index 00000000..8389b443
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeEncryptedMail.java
@@ -0,0 +1,71 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import javax.mail.Session;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+
+import org.bouncycastle.cms.RecipientId;
+import org.bouncycastle.cms.RecipientInformation;
+import org.bouncycastle.cms.RecipientInformationStore;
+import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
+import org.bouncycastle.cms.jcajce.JceKeyTransRecipientId;
+import org.bouncycastle.mail.smime.SMIMEEnvelopedParser;
+import org.bouncycastle.mail.smime.SMIMEUtil;
+import org.bouncycastle.mail.smime.util.SharedFileInputStream;
+
+/**
+ * a simple example that reads an encrypted email using the large file model.
+ * <p>
+ * The key store can be created using the class in
+ * org.bouncycastle.jce.examples.PKCS12Example - the program expects only one
+ * key to be present.
+ */
+public class ReadLargeEncryptedMail
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ if (args.length != 3)
+ {
+ System.err.println("usage: ReadLargeEncryptedMail pkcs12Keystore password outputFile");
+ System.exit(0);
+ }
+
+ //
+ // Open the key store
+ //
+ KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
+ String keyAlias = ExampleUtils.findKeyAlias(ks, args[0], args[1].toCharArray());
+
+ //
+ // find the certificate for the private key and generate a
+ // suitable recipient identifier.
+ //
+ X509Certificate cert = (X509Certificate)ks.getCertificate(keyAlias);
+ RecipientId recId = new JceKeyTransRecipientId(cert);
+
+ //
+ // Get a Session object with the default properties.
+ //
+ Properties props = System.getProperties();
+
+ Session session = Session.getDefaultInstance(props, null);
+
+ MimeMessage msg = new MimeMessage(session, new SharedFileInputStream("encrypted.message"));
+
+ SMIMEEnvelopedParser m = new SMIMEEnvelopedParser(msg);
+
+ RecipientInformationStore recipients = m.getRecipientInfos();
+ RecipientInformation recipient = recipients.get(recId);
+
+ MimeBodyPart res = SMIMEUtil.toMimeBodyPart(recipient.getContentStream(new JceKeyTransEnvelopedRecipient((PrivateKey)ks.getKey(keyAlias, null)).setProvider("BC")));
+
+ ExampleUtils.dumpContent(res, args[2]);
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeSignedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeSignedMail.java
new file mode 100644
index 00000000..91074337
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadLargeSignedMail.java
@@ -0,0 +1,125 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+
+import javax.mail.Session;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cms.SignerInformation;
+import org.bouncycastle.cms.SignerInformationStore;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.mail.smime.SMIMESignedParser;
+import org.bouncycastle.mail.smime.util.SharedFileInputStream;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.bouncycastle.util.Store;
+
+/**
+ * a simple example that reads a basic SMIME signed mail file.
+ */
+public class ReadLargeSignedMail
+{
+ private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
+
+ /**
+ * verify the signature (assuming the cert is contained in the message)
+ */
+ private static void verify(
+ SMIMESignedParser s)
+ throws Exception
+ {
+ //
+ // extract the information to verify the signatures.
+ //
+
+ //
+ // certificates and crls passed in the signature - this must happen before
+ // s.getSignerInfos()
+ //
+ Store certs = s.getCertificates();
+
+ //
+ // SignerInfo blocks which contain the signatures
+ //
+ SignerInformationStore signers = s.getSignerInfos();
+
+ Collection c = signers.getSigners();
+ Iterator it = c.iterator();
+
+ //
+ // check each signer
+ //
+ while (it.hasNext())
+ {
+ SignerInformation signer = (SignerInformation)it.next();
+ Collection certCollection = certs.getMatches(signer.getSID());
+
+ Iterator certIt = certCollection.iterator();
+ X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate((X509CertificateHolder)certIt.next());
+
+
+ //
+ // verify that the sig is correct and that it was generated
+ // when the certificate was current
+ //
+ if (signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert)))
+ {
+ System.out.println("signature verified");
+ }
+ else
+ {
+ System.out.println("signature failed!");
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ throws Exception
+ {
+ //
+ // Get a Session object with the default properties.
+ //
+ Properties props = System.getProperties();
+
+ Session session = Session.getDefaultInstance(props, null);
+
+ MimeMessage msg = new MimeMessage(session, new SharedFileInputStream("signed.message"));
+
+ //
+ // make sure this was a multipart/signed message - there should be
+ // two parts as we have one part for the content that was signed and
+ // one part for the actual signature.
+ //
+ if (msg.isMimeType("multipart/signed"))
+ {
+ SMIMESignedParser s = new SMIMESignedParser(new JcaDigestCalculatorProviderBuilder().build(),
+ (MimeMultipart)msg.getContent());
+
+ System.out.println("Status:");
+
+ verify(s);
+ }
+ else if (msg.isMimeType("application/pkcs7-mime"))
+ {
+ //
+ // in this case the content is wrapped in the signature block.
+ //
+ SMIMESignedParser s = new SMIMESignedParser(new JcaDigestCalculatorProviderBuilder().build(), msg);
+
+ System.out.println("Status:");
+
+ verify(s);
+ }
+ else
+ {
+ System.err.println("Not a signed message!");
+ }
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadSignedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadSignedMail.java
new file mode 100644
index 00000000..370106d9
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/ReadSignedMail.java
@@ -0,0 +1,176 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.FileInputStream;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+
+import javax.mail.BodyPart;
+import javax.mail.Multipart;
+import javax.mail.Session;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cms.SignerInformation;
+import org.bouncycastle.cms.SignerInformationStore;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.mail.smime.SMIMESigned;
+import org.bouncycastle.util.Store;
+
+/**
+ * a simple example that reads a basic SMIME signed mail file.
+ */
+public class ReadSignedMail
+{
+ private static final String BC = BouncyCastleProvider.PROVIDER_NAME;
+
+ /**
+ * verify the signature (assuming the cert is contained in the message)
+ */
+ private static void verify(
+ SMIMESigned s)
+ throws Exception
+ {
+ //
+ // extract the information to verify the signatures.
+ //
+
+ //
+ // certificates and crls passed in the signature
+ //
+ Store certs = s.getCertificates();
+
+ //
+ // SignerInfo blocks which contain the signatures
+ //
+ SignerInformationStore signers = s.getSignerInfos();
+
+ Collection c = signers.getSigners();
+ Iterator it = c.iterator();
+
+ //
+ // check each signer
+ //
+ while (it.hasNext())
+ {
+ SignerInformation signer = (SignerInformation)it.next();
+ Collection certCollection = certs.getMatches(signer.getSID());
+
+ Iterator certIt = certCollection.iterator();
+ X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate((X509CertificateHolder)certIt.next());
+
+ //
+ // verify that the sig is correct and that it was generated
+ // when the certificate was current
+ //
+ if (signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert)))
+ {
+ System.out.println("signature verified");
+ }
+ else
+ {
+ System.out.println("signature failed!");
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ throws Exception
+ {
+ //
+ // Get a Session object with the default properties.
+ //
+ Properties props = System.getProperties();
+
+ Session session = Session.getDefaultInstance(props, null);
+
+ MimeMessage msg = new MimeMessage(session, new FileInputStream("signed.message"));
+
+ //
+ // make sure this was a multipart/signed message - there should be
+ // two parts as we have one part for the content that was signed and
+ // one part for the actual signature.
+ //
+ if (msg.isMimeType("multipart/signed"))
+ {
+ SMIMESigned s = new SMIMESigned(
+ (MimeMultipart)msg.getContent());
+
+ //
+ // extract the content
+ //
+ MimeBodyPart content = s.getContent();
+
+ System.out.println("Content:");
+
+ Object cont = content.getContent();
+
+ if (cont instanceof String)
+ {
+ System.out.println((String)cont);
+ }
+ else if (cont instanceof Multipart)
+ {
+ Multipart mp = (Multipart)cont;
+ int count = mp.getCount();
+ for (int i = 0; i < count; i++)
+ {
+ BodyPart m = mp.getBodyPart(i);
+ Object part = m.getContent();
+
+ System.out.println("Part " + i);
+ System.out.println("---------------------------");
+
+ if (part instanceof String)
+ {
+ System.out.println((String)part);
+ }
+ else
+ {
+ System.out.println("can't print...");
+ }
+ }
+ }
+
+ System.out.println("Status:");
+
+ verify(s);
+ }
+ else if (msg.isMimeType("application/pkcs7-mime")
+ || msg.isMimeType("application/x-pkcs7-mime"))
+ {
+ //
+ // in this case the content is wrapped in the signature block.
+ //
+ SMIMESigned s = new SMIMESigned(msg);
+
+ //
+ // extract the content
+ //
+ MimeBodyPart content = s.getContent();
+
+ System.out.println("Content:");
+
+ Object cont = content.getContent();
+
+ if (cont instanceof String)
+ {
+ System.out.println((String)cont);
+ }
+
+ System.out.println("Status:");
+
+ verify(s);
+ }
+ else
+ {
+ System.err.println("Not a signed message!");
+ }
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/SendSignedAndEncryptedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/SendSignedAndEncryptedMail.java
new file mode 100644
index 00000000..8861152e
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/SendSignedAndEncryptedMail.java
@@ -0,0 +1,192 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import javax.activation.CommandMap;
+import javax.activation.MailcapCommandMap;
+import javax.mail.Message;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.cms.AttributeTable;
+import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
+import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
+import org.bouncycastle.asn1.smime.SMIMECapability;
+import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
+import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.cert.jcajce.JcaCertStore;
+import org.bouncycastle.cms.CMSAlgorithm;
+import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
+import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
+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.SMIMESignedGenerator;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.util.Strings;
+
+/**
+ * Example that sends a signed and encrypted mail message.
+ */
+public class SendSignedAndEncryptedMail
+{
+ public static void main(String args[])
+ {
+ if (args.length != 5)
+ {
+ System.err
+ .println("usage: SendSignedAndEncryptedMail <pkcs12Keystore> <password> <keyalias> <smtp server> <email address>");
+ System.exit(0);
+ }
+
+ try
+ {
+ MailcapCommandMap mailcap = (MailcapCommandMap)CommandMap
+ .getDefaultCommandMap();
+
+ mailcap
+ .addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
+ mailcap
+ .addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
+ mailcap
+ .addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
+ mailcap
+ .addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
+ mailcap
+ .addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
+
+ CommandMap.setDefaultCommandMap(mailcap);
+
+ /* Add BC */
+ Security.addProvider(new BouncyCastleProvider());
+
+ /* Open the keystore */
+ KeyStore keystore = KeyStore.getInstance("PKCS12", "BC");
+ keystore.load(new FileInputStream(args[0]), args[1].toCharArray());
+ Certificate[] chain = keystore.getCertificateChain(args[2]);
+
+ /* Get the private key to sign the message with */
+ PrivateKey privateKey = (PrivateKey)keystore.getKey(args[2],
+ args[1].toCharArray());
+ if (privateKey == null)
+ {
+ throw new Exception("cannot find private key for alias: "
+ + args[2]);
+ }
+
+ /* Create the message to sign and encrypt */
+ Properties props = System.getProperties();
+ props.put("mail.smtp.host", args[3]);
+ Session session = Session.getDefaultInstance(props, null);
+
+ MimeMessage body = new MimeMessage(session);
+ body.setFrom(new InternetAddress(args[4]));
+ body.setRecipient(Message.RecipientType.TO, new InternetAddress(
+ args[4]));
+ body.setSubject("example encrypted message");
+ body.setContent("example encrypted message", "text/plain");
+ body.saveChanges();
+
+ /* Create the SMIMESignedGenerator */
+ SMIMECapabilityVector capabilities = new SMIMECapabilityVector();
+ capabilities.addCapability(SMIMECapability.dES_EDE3_CBC);
+ capabilities.addCapability(SMIMECapability.rC2_CBC, 128);
+ capabilities.addCapability(SMIMECapability.dES_CBC);
+
+ ASN1EncodableVector attributes = new ASN1EncodableVector();
+ attributes.add(new SMIMEEncryptionKeyPreferenceAttribute(
+ new IssuerAndSerialNumber(
+ new X500Name(((X509Certificate)chain[0])
+ .getIssuerDN().getName()),
+ ((X509Certificate)chain[0]).getSerialNumber())));
+ attributes.add(new SMIMECapabilitiesAttribute(capabilities));
+
+ SMIMESignedGenerator signer = new SMIMESignedGenerator();
+ signer.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setSignedAttributeGenerator(new AttributeTable(attributes)).build("DSA".equals(privateKey.getAlgorithm()) ? "SHA1withDSA" : "MD5withRSA", privateKey, (X509Certificate)chain[0]));
+
+
+ /* Add the list of certs to the generator */
+ List certList = new ArrayList();
+ certList.add(chain[0]);
+ Store certs = new JcaCertStore(certList);
+ signer.addCertificates(certs);
+
+ /* Sign the message */
+ MimeMultipart mm = signer.generate(body);
+ MimeMessage signedMessage = new MimeMessage(session);
+
+ /* Set all original MIME headers in the signed message */
+ Enumeration headers = body.getAllHeaderLines();
+ while (headers.hasMoreElements())
+ {
+ signedMessage.addHeaderLine((String)headers.nextElement());
+ }
+
+ /* Set the content of the signed message */
+ signedMessage.setContent(mm);
+ signedMessage.saveChanges();
+
+ /* Create the encrypter */
+ SMIMEEnvelopedGenerator encrypter = new SMIMEEnvelopedGenerator();
+ encrypter.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator((X509Certificate)chain[0]).setProvider("BC"));
+
+ /* Encrypt the message */
+ MimeBodyPart encryptedPart = encrypter.generate(signedMessage,
+ new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC).setProvider("BC").build());
+
+ /*
+ * Create a new MimeMessage that contains the encrypted and signed
+ * content
+ */
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ encryptedPart.writeTo(out);
+
+ MimeMessage encryptedMessage = new MimeMessage(session,
+ new ByteArrayInputStream(out.toByteArray()));
+
+ /* Set all original MIME headers in the encrypted message */
+ headers = body.getAllHeaderLines();
+ while (headers.hasMoreElements())
+ {
+ String headerLine = (String)headers.nextElement();
+ /*
+ * Make sure not to override any content-* headers from the
+ * original message
+ */
+ if (!Strings.toLowerCase(headerLine).startsWith("content-"))
+ {
+ encryptedMessage.addHeaderLine(headerLine);
+ }
+ }
+
+ Transport.send(encryptedMessage);
+ }
+ catch (SMIMEException ex)
+ {
+ ex.getUnderlyingException().printStackTrace(System.err);
+ ex.printStackTrace(System.err);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace(System.err);
+ }
+ }
+}
diff --git a/mail/src/main/java/org/spongycastle/mail/smime/examples/ValidateSignedMail.java b/mail/src/main/java/org/spongycastle/mail/smime/examples/ValidateSignedMail.java
new file mode 100644
index 00000000..31961f1e
--- /dev/null
+++ b/mail/src/main/java/org/spongycastle/mail/smime/examples/ValidateSignedMail.java
@@ -0,0 +1,352 @@
+package org.bouncycastle.mail.smime.examples;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.cert.CertStore;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CollectionCertStoreParameters;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.mail.Session;
+import javax.mail.internet.MimeMessage;
+import javax.security.auth.x500.X500Principal;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.x509.X509Extension;
+import org.bouncycastle.cms.SignerInformation;
+import org.bouncycastle.i18n.ErrorBundle;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.mail.smime.validator.SignedMailValidator;
+import org.bouncycastle.x509.PKIXCertPathReviewer;
+import org.bouncycastle.x509.extension.X509ExtensionUtil;
+
+/**
+ * An Example that reads a signed mail and validates its signature. Also
+ * validating the certificate path from the signers key to a trusted entity
+ */
+public class ValidateSignedMail
+{
+
+ /*
+ * Use trusted certificates from $JAVA_HOME/lib/security/cacerts as
+ * trustanchors
+ */
+ public static final boolean useCaCerts = false;
+
+ public static void main(String[] args) throws Exception
+ {
+
+ Security.addProvider(new BouncyCastleProvider());
+
+ //
+ // Get a Session object with the default properties.
+ //
+ Properties props = System.getProperties();
+
+ Session session = Session.getDefaultInstance(props, null);
+
+ // read message
+ MimeMessage msg = new MimeMessage(session, new FileInputStream(
+ "signed.message"));
+
+ // create PKIXparameters
+ PKIXParameters param;
+
+ if (useCaCerts)
+ {
+ KeyStore caCerts = KeyStore.getInstance("JKS");
+ String javaHome = System.getProperty("java.home");
+ caCerts.load(
+ new FileInputStream(javaHome + "/lib/security/cacerts"),
+ "changeit".toCharArray());
+
+ param = new PKIXParameters(caCerts);
+ }
+ else
+ {
+ // load trustanchors from files (here we only load one)
+ Set trustanchors = new HashSet();
+ TrustAnchor trust = getTrustAnchor("trustanchor");
+
+ // create a dummy trustanchor if we can not find any trustanchor. so
+ // we can still try to validate the message
+ if (trust == null)
+ {
+ System.out
+ .println("no trustanchor file found, using a dummy trustanchor");
+ trust = getDummyTrustAnchor();
+ }
+ trustanchors.add(trust);
+
+ param = new PKIXParameters(trustanchors);
+ }
+
+ // load one ore more crls from files (here we only load one crl)
+ List crls = new ArrayList();
+ X509CRL crl = loadCRL("crl.file");
+ if (crl != null)
+ {
+ crls.add(crl);
+ }
+ CertStore certStore = CertStore.getInstance("Collection",
+ new CollectionCertStoreParameters(crls), "BC");
+
+ // add crls and enable revocation checking
+ param.addCertStore(certStore);
+ param.setRevocationEnabled(true);
+
+ // or disable revocation checking
+ // param.setRevocationEnabled(false);
+
+ verifySignedMail(msg, param);
+ }
+
+ public static final int TITLE = 0;
+ public static final int TEXT = 1;
+ public static final int SUMMARY = 2;
+ public static final int DETAIL = 3;
+
+ static int dbgLvl = DETAIL;
+
+ private static final String RESOURCE_NAME = "org.bouncycastle.mail.smime.validator.SignedMailValidatorMessages";
+
+ public static void verifySignedMail(MimeMessage msg, PKIXParameters param)
+ throws Exception
+ {
+ // set locale for the output
+ Locale loc = Locale.ENGLISH;
+ // Locale loc = Locale.GERMAN;
+
+ // validate signatures
+ SignedMailValidator validator = new SignedMailValidator(msg, param);
+
+ // iterate over all signatures and print results
+ Iterator it = validator.getSignerInformationStore().getSigners()
+ .iterator();
+ while (it.hasNext())
+ {
+ SignerInformation signer = (SignerInformation) it.next();
+ SignedMailValidator.ValidationResult result = validator
+ .getValidationResult(signer);
+ if (result.isValidSignature())
+ {
+ ErrorBundle errMsg = new ErrorBundle(RESOURCE_NAME,
+ "SignedMailValidator.sigValid");
+ System.out.println(errMsg.getText(loc));
+ }
+ else
+ {
+ ErrorBundle errMsg = new ErrorBundle(RESOURCE_NAME,
+ "SignedMailValidator.sigInvalid");
+ System.out.println(errMsg.getText(loc));
+ // print errors
+ System.out.println("Errors:");
+ Iterator errorsIt = result.getErrors().iterator();
+ while (errorsIt.hasNext())
+ {
+ ErrorBundle errorMsg = (ErrorBundle) errorsIt.next();
+ if (dbgLvl == DETAIL)
+ {
+ System.out.println("\t\t" + errorMsg.getDetail(loc));
+ }
+ else
+ {
+ System.out.println("\t\t" + errorMsg.getText(loc));
+ }
+ }
+ }
+ if (!result.getNotifications().isEmpty())
+ {
+ System.out.println("Notifications:");
+ Iterator notIt = result.getNotifications().iterator();
+ while (notIt.hasNext())
+ {
+ ErrorBundle notMsg = (ErrorBundle) notIt.next();
+ if (dbgLvl == DETAIL)
+ {
+ System.out.println("\t\t" + notMsg.getDetail(loc));
+ }
+ else
+ {
+ System.out.println("\t\t" + notMsg.getText(loc));
+ }
+ }
+ }
+ PKIXCertPathReviewer review = result.getCertPathReview();
+ if (review != null)
+ {
+ if (review.isValidCertPath())
+ {
+ System.out.println("Certificate path valid");
+ }
+ else
+ {
+ System.out.println("Certificate path invalid");
+ }
+
+ System.out.println("\nCertificate path validation results:");
+ // global errors
+ System.out.println("Errors:");
+ Iterator errorsIt = review.getErrors(-1).iterator();
+ while (errorsIt.hasNext())
+ {
+ ErrorBundle errorMsg = (ErrorBundle) errorsIt.next();
+ if (dbgLvl == DETAIL)
+ {
+ System.out.println("\t\t" + errorMsg.getDetail(loc));
+ }
+ else
+ {
+ System.out.println("\t\t" + errorMsg.getText(loc));
+ }
+ }
+
+ System.out.println("Notifications:");
+ Iterator notificationsIt = review.getNotifications(-1)
+ .iterator();
+ while (notificationsIt.hasNext())
+ {
+ ErrorBundle noteMsg = (ErrorBundle) notificationsIt.next();
+ System.out.println("\t" + noteMsg.getText(loc));
+ }
+
+ // per certificate errors and notifications
+ Iterator certIt = review.getCertPath().getCertificates()
+ .iterator();
+ int i = 0;
+ while (certIt.hasNext())
+ {
+ X509Certificate cert = (X509Certificate) certIt.next();
+ System.out.println("\nCertificate " + i + "\n========");
+ System.out.println("Issuer: "
+ + cert.getIssuerDN().getName());
+ System.out.println("Subject: "
+ + cert.getSubjectDN().getName());
+
+ // errors
+ System.out.println("\tErrors:");
+ errorsIt = review.getErrors(i).iterator();
+ while (errorsIt.hasNext())
+ {
+ ErrorBundle errorMsg = (ErrorBundle) errorsIt.next();
+ if (dbgLvl == DETAIL)
+ {
+ System.out
+ .println("\t\t" + errorMsg.getDetail(loc));
+ }
+ else
+ {
+ System.out.println("\t\t" + errorMsg.getText(loc));
+ }
+ }
+
+ // notifications
+ System.out.println("\tNotifications:");
+ notificationsIt = review.getNotifications(i).iterator();
+ while (notificationsIt.hasNext())
+ {
+ ErrorBundle noteMsg = (ErrorBundle) notificationsIt
+ .next();
+ if (dbgLvl == DETAIL)
+ {
+ System.out.println("\t\t" + noteMsg.getDetail(loc));
+ }
+ else
+ {
+ System.out.println("\t\t" + noteMsg.getText(loc));
+ }
+ }
+
+ i++;
+ }
+ }
+ }
+
+ }
+
+ protected static TrustAnchor getTrustAnchor(String trustcert)
+ throws Exception
+ {
+ X509Certificate cert = loadCert(trustcert);
+ if (cert != null)
+ {
+ byte[] ncBytes = cert
+ .getExtensionValue(X509Extension.nameConstraints.getId());
+
+ if (ncBytes != null)
+ {
+ ASN1Encodable extValue = X509ExtensionUtil
+ .fromExtensionValue(ncBytes);
+ return new TrustAnchor(cert, extValue.toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+ return new TrustAnchor(cert, null);
+ }
+ return null;
+ }
+
+ protected static X509Certificate loadCert(String certfile)
+ {
+ X509Certificate cert = null;
+ try
+ {
+ InputStream in = new FileInputStream(certfile);
+
+ CertificateFactory cf = CertificateFactory.getInstance("X.509",
+ "BC");
+ cert = (X509Certificate) cf.generateCertificate(in);
+ }
+ catch (Exception e)
+ {
+ System.out.println("certfile \"" + certfile
+ + "\" not found - classpath is "
+ + System.getProperty("java.class.path"));
+ }
+ return cert;
+ }
+
+ protected static X509CRL loadCRL(String crlfile)
+ {
+ X509CRL crl = null;
+ try
+ {
+ InputStream in = new FileInputStream(crlfile);
+
+ CertificateFactory cf = CertificateFactory.getInstance("X.509",
+ "BC");
+ crl = (X509CRL) cf.generateCRL(in);
+ }
+ catch (Exception e)
+ {
+ System.out.println("crlfile \"" + crlfile
+ + "\" not found - classpath is "
+ + System.getProperty("java.class.path"));
+ }
+ return crl;
+ }
+
+ private static TrustAnchor getDummyTrustAnchor() throws Exception
+ {
+ X500Principal principal = new X500Principal("CN=Dummy Trust Anchor");
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
+ kpg.initialize(1024, new SecureRandom());
+ PublicKey trustPubKey = kpg.generateKeyPair().getPublic();
+ return new TrustAnchor(principal, trustPubKey, null);
+ }
+
+}