aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/SMIMEGenerator.java
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/SMIMEGenerator.java')
-rw-r--r--libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/SMIMEGenerator.java223
1 files changed, 223 insertions, 0 deletions
diff --git a/libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/SMIMEGenerator.java b/libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/SMIMEGenerator.java
new file mode 100644
index 000000000..168cc4a42
--- /dev/null
+++ b/libraries/spongycastle/mail/src/main/java/org/spongycastle/mail/smime/SMIMEGenerator.java
@@ -0,0 +1,223 @@
+package org.bouncycastle.mail.smime;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.crypto.KeyGenerator;
+import javax.mail.Header;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Session;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+
+import org.bouncycastle.cms.CMSEnvelopedGenerator;
+import org.bouncycastle.util.Strings;
+
+/**
+ * super class of the various generators.
+ */
+public class SMIMEGenerator
+{
+ private static Map BASE_CIPHER_NAMES = new HashMap();
+
+ static
+ {
+ BASE_CIPHER_NAMES.put(CMSEnvelopedGenerator.DES_EDE3_CBC, "DESEDE");
+ BASE_CIPHER_NAMES.put(CMSEnvelopedGenerator.AES128_CBC, "AES");
+ BASE_CIPHER_NAMES.put(CMSEnvelopedGenerator.AES192_CBC, "AES");
+ BASE_CIPHER_NAMES.put(CMSEnvelopedGenerator.AES256_CBC, "AES");
+ }
+
+ protected boolean useBase64 = true;
+ protected String encoding = "base64"; // default sets base64
+
+ /**
+ * base constructor
+ */
+ protected SMIMEGenerator()
+ {
+ }
+
+ /**
+ * set the content-transfer-encoding for the CMS block (enveloped data, signature, etc...) in the message.
+ *
+ * @param encoding the encoding to use, default "base64", use "binary" for a binary encoding.
+ */
+ public void setContentTransferEncoding(
+ String encoding)
+ {
+ this.encoding = encoding;
+ this.useBase64 = Strings.toLowerCase(encoding).equals("base64");
+ }
+
+ /**
+ * Make sure we have a valid content body part - setting the headers
+ * with defaults if neccessary.
+ */
+ protected MimeBodyPart makeContentBodyPart(
+ MimeBodyPart content)
+ throws SMIMEException
+ {
+ //
+ // add the headers to the body part - if they are missing, in
+ // the event they have already been set the content settings override
+ // any defaults that might be set.
+ //
+ try
+ {
+ MimeMessage msg = new MimeMessage((Session)null);
+
+ Enumeration e = content.getAllHeaders();
+
+ msg.setDataHandler(content.getDataHandler());
+
+ while (e.hasMoreElements())
+ {
+ Header hdr =(Header)e.nextElement();
+
+ msg.setHeader(hdr.getName(), hdr.getValue());
+ }
+
+ msg.saveChanges();
+
+ //
+ // we do this to make sure at least the default headers are
+ // set in the body part.
+ //
+ e = msg.getAllHeaders();
+
+ while (e.hasMoreElements())
+ {
+ Header hdr =(Header)e.nextElement();
+
+ if (Strings.toLowerCase(hdr.getName()).startsWith("content-"))
+ {
+ content.setHeader(hdr.getName(), hdr.getValue());
+ }
+ }
+ }
+ catch (MessagingException e)
+ {
+ throw new SMIMEException("exception saving message state.", e);
+ }
+
+ return content;
+ }
+
+ /**
+ * extract an appropriate body part from the passed in MimeMessage
+ */
+ protected MimeBodyPart makeContentBodyPart(
+ MimeMessage message)
+ throws SMIMEException
+ {
+ MimeBodyPart content = new MimeBodyPart();
+
+ //
+ // add the headers to the body part.
+ //
+ try
+ {
+ message.removeHeader("Message-Id");
+ message.removeHeader("Mime-Version");
+
+ // JavaMail has a habit of reparsing some content types, if the bodypart is
+ // a multipart it might be signed, we rebuild the body part using the raw input stream for the message.
+ try
+ {
+ if (message.getContent() instanceof Multipart)
+ {
+ content.setContent(message.getRawInputStream(), message.getContentType());
+
+ extractHeaders(content, message);
+
+ return content;
+ }
+ }
+ catch (MessagingException e)
+ {
+ // fall back to usual method below
+ }
+
+ content.setContent(message.getContent(), message.getContentType());
+
+ content.setDataHandler(message.getDataHandler());
+
+ extractHeaders(content, message);
+ }
+ catch (MessagingException e)
+ {
+ throw new SMIMEException("exception saving message state.", e);
+ }
+ catch (IOException e)
+ {
+ throw new SMIMEException("exception getting message content.", e);
+ }
+
+ return content;
+ }
+
+ private void extractHeaders(MimeBodyPart content, MimeMessage message)
+ throws MessagingException
+ {
+ Enumeration e = message.getAllHeaders();
+
+ while (e.hasMoreElements())
+ {
+ Header hdr =(Header)e.nextElement();
+
+ content.addHeader(hdr.getName(), hdr.getValue());
+ }
+ }
+
+ protected KeyGenerator createSymmetricKeyGenerator(
+ String encryptionOID,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ return createKeyGenerator(encryptionOID, provider);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ try
+ {
+ String algName = (String)BASE_CIPHER_NAMES.get(encryptionOID);
+ if (algName != null)
+ {
+ return createKeyGenerator(algName, provider);
+ }
+ }
+ catch (NoSuchAlgorithmException ex)
+ {
+ // ignore
+ }
+ if (provider != null)
+ {
+ return createSymmetricKeyGenerator(encryptionOID, null);
+ }
+ throw e;
+ }
+ }
+
+ private KeyGenerator createKeyGenerator(
+ String algName,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider != null)
+ {
+ return KeyGenerator.getInstance(algName, provider);
+ }
+ else
+ {
+ return KeyGenerator.getInstance(algName);
+ }
+ }
+}