/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 javax.crypto;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

/**
 * A {@code SealedObject} is a wrapper around a {@code serializable} object
 * instance and encrypts it using a cryptographic cipher.
 *
 * <p>Since a {@code SealedObject} instance is serializable it can
 * either be stored or transmitted over an insecure channel.
 *
 * <p>The wrapped object can later be decrypted (unsealed) using the corresponding
 * key and then be deserialized to retrieve the original object. The sealed
 * object itself keeps track of the cipher and corresponding parameters.
 */
public class SealedObject implements Serializable {

    private static final long serialVersionUID = 4482838265551344752L;

    /**
     * The cipher's {@link AlgorithmParameters} in encoded format.
     * Equivalent to {@code cipher.getParameters().getEncoded()},
     * or null if the cipher did not use any parameters.
     */
    protected byte[] encodedParams;

    private byte[] encryptedContent;
    private String sealAlg;
    private String paramsAlg;

    private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
        // We do unshared reads here to ensure we have our own clones of the byte[]s.
        encodedParams = (byte[]) s.readUnshared();
        encryptedContent = (byte[]) s.readUnshared();
        // These are regular shared reads because the algorithms used by a given stream are
        // almost certain to the be same for each object, and String is immutable anyway,
        // so there's no security concern about sharing.
        sealAlg = (String) s.readObject();
        paramsAlg = (String) s.readObject();
    }

    /**
     * Creates a new {@code SealedObject} instance wrapping the specified object
     * and sealing it using the specified cipher.
     * <p>
     * The cipher must be fully initialized.
     *
     * @param object
     *            the object to seal, can be {@code null}.
     * @param c
     *            the cipher to encrypt the object.
     * @throws IOException
     *             if the serialization fails.
     * @throws IllegalBlockSizeException
     *             if the specified cipher is a block cipher and the length of
     *             the serialized data is not a multiple of the ciphers block
     *             size.
     * @throws NullPointerException
     *             if the cipher is {@code null}.
     */
    public SealedObject(Serializable object, Cipher c)
                throws IOException, IllegalBlockSizeException {
        if (c == null) {
            throw new NullPointerException("c == null");
        }
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(object);
            oos.flush();
            AlgorithmParameters ap = c.getParameters();
            this.encodedParams = (ap == null) ? null : ap.getEncoded();
            this.paramsAlg = (ap == null) ? null : ap.getAlgorithm();
            this.sealAlg = c.getAlgorithm();
            this.encryptedContent = c.doFinal(bos.toByteArray());
        } catch (BadPaddingException e) {
            // should be never thrown because the cipher
            // should be initialized for encryption
            throw new IOException(e.toString());
        }
    }

    /**
     * Creates a new {@code SealedObject} instance by copying the data from
     * the specified object.
     *
     * @param so
     *            the object to copy.
     */
    protected SealedObject(SealedObject so) {
        if (so == null) {
            throw new NullPointerException("so == null");
        }
        this.encryptedContent = so.encryptedContent;
        this.encodedParams = so.encodedParams;
        this.sealAlg = so.sealAlg;
        this.paramsAlg = so.paramsAlg;
    }

    /**
     * Returns the algorithm this object was sealed with.
     *
     * @return the algorithm this object was sealed with.
     */
    public final String getAlgorithm() {
        return sealAlg;
    }

    /**
     * Returns the wrapped object, decrypting it using the specified key.
     *
     * @param key
     *            the key to decrypt the data with.
     * @return the encapsulated object.
     * @throws IOException
     *             if deserialization fails.
     * @throws ClassNotFoundException
     *             if deserialization fails.
     * @throws NoSuchAlgorithmException
     *             if the algorithm to decrypt the data is not available.
     * @throws InvalidKeyException
     *             if the specified key cannot be used to decrypt the data.
     */
    public final Object getObject(Key key)
                throws IOException, ClassNotFoundException,
                       NoSuchAlgorithmException, InvalidKeyException {
        if (key == null) {
            throw new InvalidKeyException("key == null");
        }
        try {
            Cipher cipher = Cipher.getInstance(sealAlg);
            if ((paramsAlg != null) && (paramsAlg.length() != 0)) {
                AlgorithmParameters params =
                    AlgorithmParameters.getInstance(paramsAlg);
                params.init(encodedParams);
                cipher.init(Cipher.DECRYPT_MODE, key, params);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, key);
            }
            byte[] serialized = cipher.doFinal(encryptedContent);
            ObjectInputStream ois =
                    new ObjectInputStream(
                            new ByteArrayInputStream(serialized));
            return ois.readObject();
        } catch (NoSuchPaddingException e)  {
            // should not be thrown because cipher text was made
            // with existing padding
            throw new NoSuchAlgorithmException(e.toString());
        } catch (InvalidAlgorithmParameterException e) {
            // should not be thrown because cipher text was made
            // with correct algorithm parameters
            throw new NoSuchAlgorithmException(e.toString());
        } catch (IllegalBlockSizeException e) {
            // should not be thrown because the cipher text
            // was correctly made
            throw new NoSuchAlgorithmException(e.toString());
        } catch (BadPaddingException e) {
            // should not be thrown because the cipher text
            // was correctly made
            throw new NoSuchAlgorithmException(e.toString());
        } catch (IllegalStateException  e) {
            // should never be thrown because cipher is initialized
            throw new NoSuchAlgorithmException(e.toString());
        }
    }

    /**
     * Returns the wrapped object, decrypting it using the specified
     * cipher.
     *
     * @param c
     *            the cipher to decrypt the data.
     * @return the encapsulated object.
     * @throws IOException
     *             if deserialization fails.
     * @throws ClassNotFoundException
     *             if deserialization fails.
     * @throws IllegalBlockSizeException
     *             if the specified cipher is a block cipher and the length of
     *             the serialized data is not a multiple of the ciphers block
     *             size.
     * @throws BadPaddingException
     *             if the padding of the data does not match the padding scheme.
     */
    public final Object getObject(Cipher c)
                throws IOException, ClassNotFoundException,
                       IllegalBlockSizeException, BadPaddingException {
        if (c == null) {
            throw new NullPointerException("c == null");
        }
        byte[] serialized = c.doFinal(encryptedContent);
        ObjectInputStream ois =
                new ObjectInputStream(
                        new ByteArrayInputStream(serialized));
        return ois.readObject();
    }

    /**
     * Returns the wrapped object, decrypting it using the specified key. The
     * specified provider is used to retrieve the cipher algorithm.
     *
     * @param key
     *            the key to decrypt the data.
     * @param provider
     *            the name of the provider that provides the cipher algorithm.
     * @return the encapsulated object.
     * @throws IOException
     *             if deserialization fails.
     * @throws ClassNotFoundException
     *             if deserialization fails.
     * @throws NoSuchAlgorithmException
     *             if the algorithm used to decrypt the data is not available.
     * @throws NoSuchProviderException
     *             if the specified provider is not available.
     * @throws InvalidKeyException
     *             if the specified key cannot be used to decrypt the data.
     */
    public final Object getObject(Key key, String provider)
                throws IOException, ClassNotFoundException,
                       NoSuchAlgorithmException, NoSuchProviderException,
                       InvalidKeyException {
        if (provider == null || provider.isEmpty()) {
            throw new IllegalArgumentException("provider name empty or null");
        }
        try {
            Cipher cipher = Cipher.getInstance(sealAlg, provider);
            if ((paramsAlg != null) && (paramsAlg.length() != 0)) {
                AlgorithmParameters params =
                    AlgorithmParameters.getInstance(paramsAlg);
                params.init(encodedParams);
                cipher.init(Cipher.DECRYPT_MODE, key, params);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, key);
            }
            byte[] serialized = cipher.doFinal(encryptedContent);
            ObjectInputStream ois =
                    new ObjectInputStream(
                            new ByteArrayInputStream(serialized));
            return ois.readObject();
        } catch (NoSuchPaddingException e)  {
            // should not be thrown because cipher text was made
            // with existing padding
            throw new NoSuchAlgorithmException(e.toString());
        } catch (InvalidAlgorithmParameterException e) {
            // should not be thrown because cipher text was made
            // with correct algorithm parameters
            throw new NoSuchAlgorithmException(e.toString());
        } catch (IllegalBlockSizeException e) {
            // should not be thrown because the cipher text
            // was correctly made
            throw new NoSuchAlgorithmException(e.toString());
        } catch (BadPaddingException e) {
            // should not be thrown because the cipher text
            // was correctly made
            throw new NoSuchAlgorithmException(e.toString());
        } catch (IllegalStateException  e) {
            // should never be thrown because cipher is initialized
            throw new NoSuchAlgorithmException(e.toString());
        }
    }
}
