/* SignedObject.java --- Signed Object Class
   Copyright (C) 1999, 2003, Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.security;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * <code>SignedObject</code> is used for storing runtime objects whose
 * integrity cannot be compromised without being detected.
 *
 * <p><code>SignedObject</code> contains a {@link Serializable} object which is
 * yet to be signed and a digital signature of that object.</p>
 *
 * <p>The signed copy is a "deep copy" (in serialized form) of an original
 * object. Any changes to that original instance are not reflected in the
 * enclosed copy inside this <code>SignedObject</code>.</p>
 *
 * <p>Several things to note are that, first there is no need to initialize the
 * signature engine as this class will handle that automatically. Second,
 * verification will only succeed if the public key corresponds to the private
 * key used to generate the digital signature inside this
 * <code>SignedObject</code>.</p>
 *
 * <p>For fexibility, the signature engine can be specified in the constructor
 * or the <code>verify()</code> method. Programmers wishing to verify
 * <code>SignedObject</code>s should be aware of the {@link Signature} engine
 * they use. A malicious or flawed {@link Signature} implementation may always
 * return true on verification thus circumventing the intended secrity check
 * provided by the <code>SignedObject</code>.</p>
 *
 * <p>The GNU security provider offers an implementation of the standard NIST
 * DSA which uses "DSA" and "SHA-1". It can be specified by "SHA/DSA",
 * "SHA-1/DSA" or its OID. If the RSA signature algorithm is provided then it
 * could be "MD2/RSA". "MD5/RSA", or "SHA-1/RSA". The algorithm must be
 * specified because there is no default.</p>
 *
 * @author Mark Benvenuto (ivymccough@worldnet.att.net)
 * @since 1.2
 * @see Signature
 */
public final class SignedObject implements Serializable
{
  private static final long serialVersionUID = 720502720485447167L;

  /** @serial */
  private byte[] content;
  /** @serial */
  private byte[] signature;
  /** @serial */
  private String thealgorithm;

  /**
   * Constructs a new instance of <code>SignedObject</code> from a
   * {@link Serializable} object. The object is signed with a designated
   * private key and a signature engine.
   *
   * @param object
   *          the object to sign.
   * @param signingKey
   *          the key to use.
   * @param signingEngine
   *          the signature engine to use.
   * @throws IOException
   *           if a serialization error occurred.
   * @throws InvalidKeyException
   *           if the key is invalid.
   * @throws SignatureException
   *           if a signing error occurs.
   */
  public SignedObject(Serializable object, PrivateKey signingKey,
                      Signature signingEngine)
    throws IOException, InvalidKeyException, SignatureException
  {
    thealgorithm = signingEngine.getAlgorithm();

    ByteArrayOutputStream ostream = new ByteArrayOutputStream();
    ObjectOutputStream p = new ObjectOutputStream(ostream);
    p.writeObject(object);
    p.flush();
    p.close();

    content = ostream.toByteArray();

    signingEngine.initSign(signingKey);
    signingEngine.update(content);
    signature = signingEngine.sign();
  }

  /**
   * Returns the encapsulated object. The object is de-serialized before being
   * returned.
   *
   * @return the encapsulated object.
   * @throws IOException
   *           if a de-serialization error occurs.
   * @throws ClassNotFoundException
   *           if the encapsulated object's class was not found.
   */
  public Object getObject() throws IOException, ClassNotFoundException
  {
    ByteArrayInputStream bais = new ByteArrayInputStream(content);
    ObjectInput oi = new ObjectInputStream(bais);
    Object obj = oi.readObject();
    oi.close();
    bais.close();

    return obj;
  }

  /**
   * Returns the signature bytes of the encapsulated object.
   *
   * @return the signature bytes of the encapsulated object.
   */
  public byte[] getSignature()
  {
    return (byte[]) signature.clone();

  }

  /**
   * Returns the name of the signature algorithm.
   *
   * @return the name of the signature algorithm.
   */
  public String getAlgorithm()
  {
    return thealgorithm;
  }

  /**
   * Verifies the encapsulated digital signature by checking that it was
   * generated by the owner of a designated public key.
   *
   * @param verificationKey
   *          the public key to use.
   * @param verificationEngine
   *          the signature engine to use.
   * @return <code>true</code> if signature is correct, <code>false</code>
   *         otherwise.
   * @throws InvalidKeyException
   *           if the key is invalid.
   * @throws SignatureException
   *           if verification fails.
   */
  public boolean verify(PublicKey verificationKey, Signature verificationEngine)
    throws InvalidKeyException, SignatureException
  {
    verificationEngine.initVerify(verificationKey);
    verificationEngine.update(content);
    return verificationEngine.verify(signature);
  }

  /** Called to restore the state of the SignedObject from a stream. */
  private void readObject(ObjectInputStream s)
    throws IOException, ClassNotFoundException
  {
    s.defaultReadObject();
    content = (byte[]) content.clone();
    signature = (byte[]) signature.clone();
  }
}
