eu.peppol.as2.SMimeMessageFactory.java Source code

Java tutorial

Introduction

Here is the source code for eu.peppol.as2.SMimeMessageFactory.java

Source

/*
 * Copyright (c) 2010 - 2015 Norwegian Agency for Pupblic Government and eGovernment (Difi)
 *
 * This file is part of Oxalis.
 *
 * Licensed under the EUPL, Version 1.1 or  as soon they will be approved by the European Commission
 * - subsequent versions of the EUPL (the "Licence"); You may not use this work except in compliance with the Licence.
 *
 * You may obtain a copy of the Licence at:
 *
 * https://joinup.ec.europa.eu/software/page/eupl5
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the Licence
 *  is distributed on an "AS IS" basis,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licence for the specific language governing permissions and limitations under the Licence.
 *
 */

package eu.peppol.as2;

import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.mail.smime.SMIMEException;
import org.bouncycastle.mail.smime.SMIMESignedGenerator;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.util.Store;

import javax.activation.MimeType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * Creates signed Mime messages
 */
public class SMimeMessageFactory {

    private final PrivateKey privateKey;
    private final X509Certificate ourCertificate;

    public SMimeMessageFactory(PrivateKey privateKey, X509Certificate ourCertificate) {
        this.privateKey = privateKey;
        this.ourCertificate = ourCertificate;
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    /**
     * Creates an S/MIME message from the supplied String, having the supplied MimeType as the "content-type".
     *
     * @param msg holds the payload of the message
     * @param mimeType the MIME type to be used as the "Content-Type"
     */
    public MimeMessage createSignedMimeMessage(final String msg, MimeType mimeType) {
        return createSignedMimeMessage(new ByteArrayInputStream(msg.getBytes()), mimeType);
    }

    /** Creates a new S/MIME message having the supplied MimeType as the "content-type" */
    public MimeMessage createSignedMimeMessage(final InputStream inputStream, MimeType mimeType) {
        MimeBodyPart mimeBodyPart = MimeMessageHelper.createMimeBodyPart(inputStream, mimeType);
        return createSignedMimeMessage(mimeBodyPart);
    }

    /** Creates an S/MIME message using the supplied MimeBodyPart. The signature is generated using the private key
     * as supplied in the constructor. Our certificate, which is required to verify the signature is enclosed.
     */
    public MimeMessage createSignedMimeMessage(MimeBodyPart mimeBodyPart) {

        //
        // S/MIME capabilities are required, but we simply supply an empty vector
        //
        ASN1EncodableVector signedAttrs = new ASN1EncodableVector();

        //
        // create the generator for creating an smime/signed message
        //
        SMIMESignedGenerator smimeSignedGenerator = new SMIMESignedGenerator("binary"); //also see CMSSignedGenerator ?

        //
        // 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
        //
        try {
            smimeSignedGenerator.addSignerInfoGenerator(
                    new JcaSimpleSignerInfoGeneratorBuilder().setProvider(new BouncyCastleProvider())
                            .setSignedAttributeGenerator(new AttributeTable(signedAttrs))
                            .build("SHA1withRSA", privateKey, ourCertificate));
        } catch (OperatorCreationException e) {
            throw new IllegalStateException("Unable to add Signer information. " + e.getMessage(), e);
        } catch (CertificateEncodingException e) {
            throw new IllegalStateException(
                    "Certificate encoding problems while adding signer information." + e.getMessage(), e);
        }

        //
        // add our pool of certs and crls (if any) to go with the signature
        //
        List certList = new ArrayList();
        certList.add(ourCertificate);

        //
        // create a CertStore containing the certificates we want carried
        // in the signature
        //
        Store certs = null;
        try {
            certs = new JcaCertStore(certList);
        } catch (CertificateEncodingException e) {
            throw new IllegalStateException("Unable to create JcaCertStore with our certificate. " + e.getMessage(),
                    e);
        }
        smimeSignedGenerator.addCertificates(certs);

        //
        // Signs the supplied MimeBodyPart
        //
        MimeMultipart mimeMultipart = null;
        try {
            mimeMultipart = smimeSignedGenerator.generate(mimeBodyPart);
        } catch (SMIMEException e) {
            throw new IllegalStateException("Unable to generate signed mime multipart." + e.getMessage(), e);
        }

        //
        // Get a Session object and create the mail message
        //
        Properties props = System.getProperties();
        Session session = Session.getDefaultInstance(props, null);

        MimeMessage mimeMessage = new MimeMessage(session);

        try {
            mimeMessage.setContent(mimeMultipart, mimeMultipart.getContentType());
        } catch (MessagingException e) {
            throw new IllegalStateException("Unable to  set Content type of MimeMessage. " + e.getMessage(), e);
        }
        try {
            mimeMessage.saveChanges();
        } catch (MessagingException e) {
            throw new IllegalStateException("Unable to save changes to Mime message. " + e.getMessage(), e);
        }

        return mimeMessage;

    }

}