All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.mime.smime.SMIMEEnvelopedWriter Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for CMS, PKCS, EAC, TSP, CMP, CRMF, OCSP, and certificate generation. This jar contains APIs for JDK 1.8 and up. The APIs can be used in conjunction with a JCE/JCA provider such as the one provided with the Bouncy Castle Cryptography APIs.

There is a newer version: 1.78.1
Show newest version
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();
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy