org.bouncycastle.mime.smime.SMIMEEnvelopedWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcpkix-jdk15to18 Show documentation
Show all versions of bcpkix-jdk15to18 Show documentation
The Bouncy Castle Java APIs for CMS, PKCS, EAC, TSP, CMP, CRMF, OCSP, and certificate generation. This jar contains APIs for JDK 1.5 to JDK 1.8. The APIs can be used in conjunction with a JCE/JCA provider such as the one provided with the Bouncy Castle Cryptography APIs.
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.
*/
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 headers = new LinkedHashMap();
String contentTransferEncoding = "base64";
public Builder()
{
for (int i = 0; i != stdHeaders.length; i++)
{
headers.put(stdHeaders[i], stdValues[i]);
}
}
/**
* Set the underlying string size for encapsulated data
*
* @param bufferSize length of octet strings to buffer the data.
*/
public Builder setBufferSize(
int bufferSize)
{
this.envGen.setBufferSize(bufferSize);
return this;
}
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.
*
* @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.
*
* @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, SMimeUtils.autoBuffer(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 backing = mimeOut;
if ("base64".equals(contentTransferEncoding))
{
backing = new Base64OutputStream(backing);
}
OutputStream main = envGen.open(SMimeUtils.createUnclosable(backing), outEnc);
return new ContentOutputStream(main, backing);
}
catch (CMSException e)
{
throw new MimeIOException(e.getMessage(), e);
}
}
private static 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(byte[] buf)
throws IOException
{
main.write(buf);
}
public void write(byte[] buf, int off, int len)
throws IOException
{
main.write(buf, off, len);
}
public void write(int i)
throws IOException
{
main.write(i);
}
public void close()
throws IOException
{
main.close();
if (backing != null)
{
backing.close();
}
}
}
}