org.dihedron.crypto.operations.encrypt.pkcs7.PKCS7EncryptingStream.java Source code

Java tutorial

Introduction

Here is the source code for org.dihedron.crypto.operations.encrypt.pkcs7.PKCS7EncryptingStream.java

Source

/**
 * Copyright (c) 2012-2014, Andrea Funto'. All rights reserved. See LICENSE for details.
 */
package org.dihedron.crypto.operations.encrypt.pkcs7;

import java.io.IOException;
import java.io.OutputStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;

import org.bouncycastle.cms.CMSAlgorithm;
import org.bouncycastle.cms.CMSEnvelopedDataStreamGenerator;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
import org.dihedron.crypto.operations.encrypt.EncryptingStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Andrea Funto'
 */
public class PKCS7EncryptingStream extends EncryptingStream {
    /**
     * The logger.
     */
    public static final Logger logger = LoggerFactory.getLogger(PKCS7EncryptingStream.class);

    /**
     * The wrapped output stream.
     */
    private OutputStream stream;

    /**
     * Constructor.
     * 
     * @param output
     *   the output stream, to which encrypted data will be written.
     * @param certificate
     *   the certificate to be used for encryption.
     */
    public PKCS7EncryptingStream(OutputStream output, Certificate certificate) {
        super(output, certificate);

        logger.info("encrypting data through certificate supporting algorithm: '{}'",
                certificate.getPublicKey().getAlgorithm());

        if (certificate instanceof X509Certificate) {
            String[] issuerInfo = ((X509Certificate) certificate).getIssuerDN().getName().split("(=|, )", -1);
            String[] subjectInfo = ((X509Certificate) certificate).getSubjectDN().getName().split("(=|, )", -1);

            logger.debug("common name (CN) : '{}'", subjectInfo[3]);
            logger.debug("address          : '{}'", subjectInfo[1]);

            for (int i = 0; i < issuerInfo.length; i += 2) {
                if (issuerInfo[i].equals("C")) {
                    logger.debug("CountryName : '{}'", issuerInfo[i + 1]);
                }
                if (issuerInfo[i].equals("O")) {
                    logger.debug("OrganizationName : '{}'", issuerInfo[i + 1]);
                }
                if (issuerInfo[i].equals("CN")) {
                    logger.debug("CommonName : '{}'", issuerInfo[i + 1]);
                }
            }
            logger.debug("certificate is valid from {} until {}", ((X509Certificate) certificate).getNotBefore(),
                    ((X509Certificate) certificate).getNotAfter());
        }

        try {
            logger.info("preparing encrypting stream...");
            CMSEnvelopedDataStreamGenerator generator = new CMSEnvelopedDataStreamGenerator();
            generator.addRecipientInfoGenerator(
                    new JceKeyTransRecipientInfoGenerator((X509Certificate) certificate).setProvider("BC"));
            stream = generator.open(output,
                    new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider("BC").build());
            logger.info("encrypting stream ready!");
        } catch (CMSException ex) {
            logger.error("CMSException: ", ex.getUnderlyingException());
        } catch (IOException e) {
            logger.error("couldn't generate enveloped signature");
        } catch (CertificateEncodingException e) {
            logger.error("certificate encoding error", e);
        }
    }

    /**
     * Writes the specified byte to this output stream. 
     * 
     * @throws IOException 
     */
    public void write(int b) throws IOException {
        logger.trace("writing 1 byte to stream");
        stream.write(b);
    }

    /**
     * Writes bytes.length bytes to this output stream.
     * 
     * @param bytes
     *   the data to be written.
     * @throws IOException 
     */
    @Override
    public void write(byte[] bytes) throws IOException {
        logger.trace("writing {} bytes to stream", bytes.length);
        stream.write(bytes);
    }

    /**
     * Writes length bytes from the specified byte array starting at the given
     * offset to this output stream.
     * 
     * @param bytes
     *   an array holding the data to be written.
     * @param offset
     *   the offset at which to start writing data.
     * @param length
     *   the number of bytes to write starting at the given offset.
     */
    @Override
    public void write(byte[] bytes, int offset, int length) throws IOException {
        logger.trace("writing {} bytes at offset {} to stream", length, offset);
        stream.write(bytes, offset, length);
    }

    /**
     * Flushes this output stream and forces any buffered output bytes to be 
     * written out to the stream.
     * 
     * @throws IOException 
     */
    @Override
    public void flush() throws IOException {
        stream.flush();
        super.flush();
    }

    /**
     * Closes this output stream and releases any system resources associated 
     * with the stream.
     * 
     * @throws IOException 
     */
    @Override
    public void close() throws IOException {
        stream.close();
        super.close();
    }
}