com.adaptris.security.StdOutput.java Source code

Java tutorial

Introduction

Here is the source code for com.adaptris.security.StdOutput.java

Source

/*
 * Copyright 2015 Adaptris Ltd.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package com.adaptris.security;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.net.util.Base64;

import com.adaptris.security.exc.AdaptrisSecurityException;
import com.adaptris.security.exc.EncryptException;
import com.adaptris.security.exc.VerifyException;

/**
 * @see Output
 * @author $Author: lchan $
 */
final class StdOutput implements Output {

    private byte[] message = null, encryptedData = null, sessionIV = null, sessionKey = null, signature = null,
            decryptedData = null;
    private int type;

    /**
     * Constructor
     * 
     * @param t the type of output
     */
    StdOutput(int t) {
        type = t;
    }

    /**
     * @see Output#getAsString()
     */
    public String getAsString() throws AdaptrisSecurityException {
        return new String(this.getBytes());
    }

    /**
     * 
     * @see com.adaptris.security.Output#getAsString(java.lang.String)
     */
    public String getAsString(String charset) throws AdaptrisSecurityException, UnsupportedEncodingException {
        return new String(this.getBytes(), charset);
    }

    /**
     * @see Output#getBytes()
     */
    public byte[] getBytes() throws AdaptrisSecurityException {
        if (this.isEncrypted() || this.isSigned()) {
            return (this.formatBase64());
        }
        return (this.getDecryptedData(true));
    }

    /**
     * @see Output#getType()
     */
    public int getType() {
        return type;
    }

    /**
     * @see Output#isEncrypted()
     */
    public boolean isEncrypted() {
        return ((this.getType() & Output.ENCRYPTED) > 0);
    }

    /**
     * @see Output#isPlain()
     */
    public boolean isPlain() {
        return ((this.getType() & Output.PLAIN) > 0);
    }

    /**
     * @see Output#isSigned()
     */
    public boolean isSigned() {
        return ((this.getType() & Output.SIGNED) > 0);
    }

    /**
     * @see #split(byte[])
     */
    void readEncryptedMessage(String fullMessage) throws AdaptrisSecurityException {
        this.split(fullMessage.getBytes());
    }

    /**
     * This splits our full data message into it's constituent parts.
     * <p>
     * This output defines the encrypted payload be a base64 payload containing,
     * in order
     * <ul>
     * <li>InitialisationVector.length</li>
     * <li>InitialisationVector</li>
     * <li>SessionKey.length</li>
     * <li>SessionKey</li>
     * <li>Data.length</li>
     * <li>Data</li>
     * <li>Signature.length</li>
     * <li>Signature</li>
     * </ul>
     * </p>
     * 
     * @param fullMessage the data to be treated as an encrypted message
     * @throws AdaptrisSecurityException if an error occurs
     */
    void split(byte[] fullMessage) throws AdaptrisSecurityException {
        try {
            message = fullMessage;
            this.split();
        } catch (Exception e) {
            throw new VerifyException("Cannot parse payload", e);
        }
    }

    /**
     * Set the encrypted data.
     * 
     * @param bytes the byte array containing the encrypted data
     */
    void setEncryptedData(byte[] bytes) {
        if ((bytes != null) && (bytes.length > 0)) {
            encryptedData = bytes;
        }
    }

    /**
     * Set the signed data.
     * 
     * @param bytes the byte array containing the signature
     */
    void setSignature(byte[] bytes) {
        if ((bytes != null) && (bytes.length > 0)) {
            signature = bytes;
        }
    }

    /**
     * Get the signature that is stored in this container
     * 
     * @return a byte array containing the signature
     */
    byte[] getSignature() {
        return signature;
    }

    /**
     * Set the session key for this encryption instance.
     * 
     * @param bytes the byte array containing the session key
     */
    void setSessionKey(byte[] bytes) {
        if ((bytes != null) && (bytes.length > 0)) {
            sessionKey = bytes;
        }
    }

    /**
     * Return the stored session key.
     * 
     * @return a byte array containing the session key
     */
    byte[] getSessionKey() {
        return sessionKey;
    }

    /**
     * Set the session initialisation vector for this encryption instance.
     * 
     * @param bytes the byte array containing the session vector
     */
    void setSessionVector(byte[] bytes) {
        if ((bytes != null) && (bytes.length > 0)) {
            sessionIV = bytes;
        }
    }

    /**
     * Get the session vector for this encryption.
     * 
     * @return a byte array containing the session vector
     */
    byte[] getSessionVector() {
        return sessionIV;
    }

    /**
     * Set the decrypted Data.
     * 
     * @param b the byte array containing the decrypted data,
     */
    void setDecryptedData(byte[] b) {
        decryptedData = b;
    }

    /**
     * Set the decrypted Data.
     * 
     * @param s the String containing the decrypted data
     */
    void setDecryptedData(String s) {
        this.setDecryptedData(s.getBytes());
    }

    /**
     * Get the encrypted data stored in this output object.
     * 
     * @param getCopy whether to return a copy of the bytes, rather than the
     *          actual bytes
     * @return a copy of the encrypted data as a byte array
     */
    byte[] getEncryptedData(boolean getCopy) {

        return (getCopy) ? copy(encryptedData) : encryptedData;
    }

    /**
     * Get the decrypted data stored in this output object.
     * 
     * @param getCopy whether to return a copy of the bytes, rather than the
     *          actual bytes
     * @return a copy of the decrypted data as a byte array
     */
    byte[] getDecryptedData(boolean getCopy) {

        return (getCopy) ? copy(decryptedData) : decryptedData;
    }

    /**
     * Set the output type.
     * 
     * @param t a type specified by the Output interface or combination thereof
     * @see Output#ENCRYPTED
     * @see Output#PLAIN
     * @see Output#SIGNED
     */
    void setType(int t) {
        type = t;
    }

    /**
     * Split this encrypted payload into it's constituent parts.
     * 
     * @see #readEncryptedMesage(byte[])
     * @throws IOException if we can't read the message
     * @throws Base64Exception if the message is not correctly encoded
     */
    private void split() throws IOException {

        ByteArrayInputStream byteStream = new ByteArrayInputStream(Base64.decodeBase64(message));
        DataInputStream in = new DataInputStream(byteStream);
        setSessionVector(read(in));
        setSessionKey(read(in));
        setEncryptedData(read(in));
        setSignature(read(in));
        in.close();
        byteStream.close();

    }

    /**
     * Return the encrypted message ready for immediate writing to file.
     * 
     * @return the bytes ready for writing.
     * @throws AdaptrisSecurityException if an error occurs
     */
    private byte[] formatBase64() throws EncryptException {

        DataOutputStream out = null;
        ByteArrayOutputStream byteStream = null;
        byte[] returnBytes = null;
        try {
            byteStream = new ByteArrayOutputStream();
            out = new DataOutputStream(byteStream);
            write(out, getSessionVector());
            write(out, getSessionKey());
            write(out, getEncryptedData(false) == null ? getDecryptedData(false) : getEncryptedData(false));
            write(out, getSignature());
            returnBytes = Base64.encodeBase64(byteStream.toByteArray());
        } catch (Exception e) {
            throw new EncryptException(e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (byteStream != null) {
                    byteStream.close();
                }
            } catch (Exception ignored) {
                ;
            }
        }
        return returnBytes;
    }

    private static void write(DataOutputStream out, byte[] bytes) throws IOException {
        if (bytes == null) {
            out.writeInt(0);
        } else {
            out.writeInt(bytes.length);
            out.write(bytes, 0, bytes.length);
        }
    }

    private static byte[] read(DataInputStream in) throws IOException {
        byte[] bytes = new byte[in.readInt()];
        if (bytes.length > 0) {
            in.read(bytes, 0, bytes.length);
        } else {
            bytes = null;
        }
        return bytes;
    }

    private static byte[] copy(byte[] source) {
        return ArrayUtils.clone(source);
    }
}