package org.bouncycastle.mime.smime;

import java.io.IOException;
import java.io.OutputStream;
import java.util.LinkedHashMap;
import java.util.Map;

import org.bouncycastle.cms.CMSAttributeTableGenerator;
import org.bouncycastle.cms.CMSEnvelopedDataStreamGenerator;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.OriginatorInformation;
import org.bouncycastle.cms.RecipientInfoGenerator;
import org.bouncycastle.mime.Headers;
import org.bouncycastle.mime.MimeIOException;
import org.bouncycastle.mime.MimeWriter;
import org.bouncycastle.mime.encoding.Base64OutputStream;
import org.bouncycastle.operator.OutputEncryptor;
import org.bouncycastle.util.Strings;

Writer for SMIME Enveloped objects.
/** * Writer for SMIME Enveloped objects. */
public class SMIMEEnvelopedWriter extends MimeWriter { public static class Builder { private static final String[] stdHeaders; private static final String[] stdValues; static { stdHeaders = new String[] { "Content-Type", "Content-Disposition", "Content-Transfer-Encoding", "Content-Description" }; stdValues = new String[] { "application/pkcs7-mime; name=\"smime.p7m\"; smime-type=enveloped-data", "attachment; filename=\"smime.p7m\"", "base64", "S/MIME Encrypted Message" }; } private final CMSEnvelopedDataStreamGenerator envGen = new CMSEnvelopedDataStreamGenerator(); private final Map<String, String> headers = new LinkedHashMap<String, String>(); String contentTransferEncoding = "base64"; public Builder() { for (int i = 0; i != stdHeaders.length; i++) { headers.put(stdHeaders[i], stdValues[i]); } } public Builder setUnprotectedAttributeGenerator(CMSAttributeTableGenerator unprotectedAttributeGenerator) { this.envGen.setUnprotectedAttributeGenerator(unprotectedAttributeGenerator); return this; } public Builder setOriginatorInfo(OriginatorInformation originatorInfo) { this.envGen.setOriginatorInfo(originatorInfo); return this; }
Specify a MIME header (name, value) pair for this builder. If the headerName already exists it will be overridden.
Params:
  • headerName – name of the MIME header.
  • headerValue – value of the MIME header.
Returns:the current Builder instance.
/** * Specify a MIME header (name, value) pair for this builder. If the headerName already exists it will * be overridden. * * @param headerName name of the MIME header. * @param headerValue value of the MIME header. * * @return the current Builder instance. */
public Builder withHeader(String headerName, String headerValue) { this.headers.put(headerName, headerValue); return this; }
Add a generator to produce the recipient info required.
Params:
  • recipientGenerator – a generator of a recipient info object.
Returns:the current Builder instance.
/** * Add a generator to produce the recipient info required. * * @param recipientGenerator a generator of a recipient info object. * * @return the current Builder instance. */
public Builder addRecipientInfoGenerator(RecipientInfoGenerator recipientGenerator) { this.envGen.addRecipientInfoGenerator(recipientGenerator); return this; } public SMIMEEnvelopedWriter build(OutputStream mimeOut, OutputEncryptor outEnc) { return new SMIMEEnvelopedWriter(this, outEnc, mimeOut); } } private final CMSEnvelopedDataStreamGenerator envGen; private final OutputEncryptor outEnc; private final OutputStream mimeOut; private final String contentTransferEncoding; private SMIMEEnvelopedWriter(Builder builder, OutputEncryptor outEnc, OutputStream mimeOut) { super(new Headers(mapToLines(builder.headers), builder.contentTransferEncoding)); this.envGen = builder.envGen; this.contentTransferEncoding = builder.contentTransferEncoding; this.outEnc = outEnc; this.mimeOut = mimeOut; } public OutputStream getContentStream() throws IOException { headers.dumpHeaders(mimeOut); mimeOut.write(Strings.toByteArray("\r\n")); try { OutputStream outStream; if ("base64".equals(contentTransferEncoding)) { outStream = new Base64OutputStream(mimeOut); return new ContentOutputStream(envGen.open(SMimeUtils.createUnclosable(outStream), outEnc), outStream); } else { return new ContentOutputStream(envGen.open(SMimeUtils.createUnclosable(mimeOut), outEnc), null); } } catch (CMSException e) { throw new MimeIOException(e.getMessage(), e); } } private class ContentOutputStream extends OutputStream { private final OutputStream main; private final OutputStream backing; ContentOutputStream(OutputStream main, OutputStream backing) { this.main = main; this.backing = backing; } public void write(int i) throws IOException { main.write(i); } public void close() throws IOException { main.close(); if (backing != null) { backing.close(); } } } }