/* Signature.java --- Signature Class
   Copyright (C) 1999, 2002, 2003, 2004  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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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 gnu.java.security.Engine;

import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;

/**
 * <p>This <code>Signature</code> class is used to provide applications the
 * functionality of a digital signature algorithm. Digital signatures are used
 * for authentication and integrity assurance of digital data.</p>
 *
 * <p>The signature algorithm can be, among others, the NIST standard <i>DSS</i>,
 * using <i>DSA</i> and <i>SHA-1</i>. The <i>DSA</i> algorithm using the
 * <i>SHA-1</i> message digest algorithm can be specified as <code>SHA1withDSA
 * </code>. In the case of <i>RSA</i>, there are multiple choices for the
 * message digest algorithm, so the signing algorithm could be specified as, for
 * example, <code>MD2withRSA</code>, <code>MD5withRSA</code>, or
 * <code>SHA1withRSA</code>. The algorithm name must be specified, as there is
 * no default.</p>
 *
 * <p>Like other algorithm-based classes in Java Security, <code>Signature</code>
 * provides implementation-independent algorithms, whereby a caller (application
 * code) requests a particular signature algorithm and is handed back a properly
 * initialized <code>Signature</code> object. It is also possible, if desired,
 * to request a particular algorithm from a particular provider. See the
 * <code>getInstance()</code> methods.</p>
 *
 * <p>Thus, there are two ways to request a <code>Signature</code> algorithm
 * object: by specifying either just an algorithm name, or both an algorithm
 * name and a package provider.</p>
 *
 * <p>If just an algorithm name is specified, the system will determine if there
 * is an implementation of the algorithm requested available in the environment,
 * and if there is more than one, if there is a preferred one.</p>
 *
 * <p>If both an algorithm name and a package provider are specified, the system
 * will determine if there is an implementation of the algorithm in the package
 * requested, and throw an exception if there is not.</p>
 *
 * <p>A <code>Signature</code> object can be used to generate and verify digital
 * signatures.</p>
 *
 * <p>There are three phases to the use of a <code>Signature</code> object for
 * either signing data or verifying a signature:</p>
 *
 * <ol>
 * <li>Initialization, with either
 *     <ul>
 *     <li>a public key, which initializes the signature for verification
 *         (see <code>initVerify()</code>), or</li>
 *     <li>a private key (and optionally a Secure Random Number Generator),
 *         which initializes the signature for signing (see
 *         {@link #initSign(PrivateKey)} and {@link #initSign(PrivateKey, SecureRandom)}
 *         ).</li>
 *     </ul></li>
 * <li>Updating<br/>
 *     Depending on the type of initialization, this will update the bytes to
 *     be signed or verified. See the update methods.<br/></li>
 * <li>Signing or Verifying a signature on all updated bytes. See the
 *     <code>sign()</code> methods and the <code>verify()</code> method.</li>
 *  </ol>
 *
 * <p>Note that this class is abstract and extends from {@link SignatureSpi} for
 * historical reasons. Application developers should only take notice of the
 * methods defined in this <code>Signature</code> class; all the methods in the
 * superclass are intended for cryptographic service providers who wish to
 * supply their own implementations of digital signature algorithms.
 *
 * @author Mark Benvenuto  (ivymccough@worldnet.att.net)
 */
public abstract class Signature extends SignatureSpi
{
  /** Service name for signatures. */
  private static final String SIGNATURE = "Signature";

  /**
   * Possible <code>state</code> value, signifying that this signature object
   * has not yet been initialized.
   */
  protected static final int UNINITIALIZED = 0;

  // Constructor.
  // ------------------------------------------------------------------------

  /**
   * Possible <code>state</code> value, signifying that this signature object
   * has been initialized for signing.
   */
  protected static final int SIGN = 2;

  /**
   * Possible <code>state</code> value, signifying that this signature object
   * has been initialized for verification.
   */
  protected static final int VERIFY = 3;

  /** Current state of this signature object. */
  protected int state = UNINITIALIZED;

  private String algorithm;
  Provider provider;

  /**
   * Creates a <code>Signature</code> object for the specified algorithm.
   *
   * @param algorithm the standard string name of the algorithm. See Appendix A
   * in the Java Cryptography Architecture API Specification &amp; Reference for
   * information about standard algorithm names.
   */
  protected Signature(String algorithm)
  {
    this.algorithm = algorithm;
    state = UNINITIALIZED;
  }

  /**
   * Generates a <code>Signature</code> object that implements the specified
   * digest algorithm. If the default provider package provides an
   * implementation of the requested digest algorithm, an instance of
   * <code>Signature</code> containing that implementation is returned. If the
   * algorithm is not available in the default package, other packages are
   * searched.
   *
   * @param algorithm the standard name of the algorithm requested. See Appendix
   * A in the Java Cryptography Architecture API Specification &amp; Reference
   * for information about standard algorithm names.
   * @return the new Signature object.
   * @throws NoSuchAlgorithmException if the algorithm is not available in the
   * environment.
   */
  public static Signature getInstance(String algorithm)
    throws NoSuchAlgorithmException
  {
    Provider[] p = Security.getProviders();
    for (int i = 0; i < p.length; i++)
      {
        try
          {
            return getInstance(algorithm, p[i]);
          }
	catch (NoSuchAlgorithmException e)
	  {
	    // Ignored.
	  }
      }

    throw new NoSuchAlgorithmException(algorithm);
  }

  /**
   * Generates a <code>Signature</code> object implementing the specified
   * algorithm, as supplied from the specified provider, if such an algorithm
   * is available from the provider.
   *
   * @param algorithm the name of the algorithm requested. See Appendix A in
   * the Java Cryptography Architecture API Specification &amp; Reference for
   * information about standard algorithm names.
   * @param provider the name of the provider.
   * @return the new <code>Signature</code> object.
   * @throws NoSuchAlgorithmException if the algorithm is not available in the
   * package supplied by the requested provider.
   * @throws NoSuchProviderException if the provider is not available in the
   * environment.
   * @throws IllegalArgumentException if the provider name is <code>null</code>
   * or empty.
   * @see Provider
   */
  public static Signature getInstance(String algorithm, String provider)
    throws NoSuchAlgorithmException, NoSuchProviderException
  {
    if (provider == null || provider.length() == 0)
      throw new IllegalArgumentException("Illegal provider");

    Provider p = Security.getProvider(provider);
    if (p == null)
      throw new NoSuchProviderException(provider);

    return getInstance(algorithm, p);
  }

  /**
   * Generates a <code>Signature</code> object implementing the specified
   * algorithm, as supplied from the specified provider, if such an algorithm
   * is available from the provider. Note: the provider doesn't have to be
   * registered.
   *
   * @param algorithm the name of the algorithm requested. See Appendix A in
   * the Java Cryptography Architecture API Specification &amp; Reference for
   * information about standard algorithm names.
   * @param provider the provider.
   * @return the new <code>Signature</code> object.
   * @throws NoSuchAlgorithmException if the <code>algorithm</code> is not
   * available in the package supplied by the requested <code>provider</code>.
   * @throws IllegalArgumentException if the <code>provider</code> is
   * <code>null</code>.
   * @since 1.4
   * @see Provider
   */
  public static Signature getInstance(String algorithm, Provider provider)
    throws NoSuchAlgorithmException
  {
    if (provider == null)
      throw new IllegalArgumentException("Illegal provider");

    Signature result = null;
    Object o = null;
    try
      {
        o = Engine.getInstance(SIGNATURE, algorithm, provider);
      }
    catch (java.lang.reflect.InvocationTargetException ite)
      {
        throw new NoSuchAlgorithmException(algorithm);
      }

    if (o instanceof SignatureSpi)
      {
        result = new DummySignature((SignatureSpi) o, algorithm);
      }
    else if (o instanceof Signature)
      {
        result = (Signature) o;
        result.algorithm = algorithm;
      }
    else
      {
        throw new NoSuchAlgorithmException(algorithm);
      }
    result.provider = provider;
    return result;
  }

  /**
   * Returns the provider of this signature object.
   *
   * @return the provider of this signature object.
   */
  public final Provider getProvider()
  {
    return provider;
  }

  /**
   * Initializes this object for verification. If this method is called again
   * with a different argument, it negates the effect of this call.
   *
   * @param publicKey the public key of the identity whose signature is going
   * to be verified.
   * @throws InvalidKeyException if the key is invalid.
   */
  public final void initVerify(PublicKey publicKey) throws InvalidKeyException
  {
    state = VERIFY;
    engineInitVerify(publicKey);
  }

  /**
   * <p>Initializes this object for verification, using the public key from the
   * given certificate.</p>
   *
   * <p>If the certificate is of type <i>X.509</i> and has a <i>key usage</i>
   * extension field marked as <i>critical</i>, and the value of the <i>key
   * usage</i> extension field implies that the public key in the certificate
   * and its corresponding private key are not supposed to be used for digital
   * signatures, an {@link InvalidKeyException} is thrown.</p>
   *
   * @param certificate the certificate of the identity whose signature is
   * going to be verified.
   * @throws InvalidKeyException if the public key in the certificate is not
   * encoded properly or does not include required parameter information or
   * cannot be used for digital signature purposes.
   */
  public final void initVerify(Certificate certificate)
    throws InvalidKeyException
  {
    state = VERIFY;
    if (certificate.getType().equals("X509"))
      {
        X509Certificate cert = (X509Certificate) certificate;
        boolean[]array = cert.getKeyUsage();
        if (array != null && array[0] == false)
          throw new InvalidKeyException(
              "KeyUsage of this Certificate indicates it cannot be used for digital signing");
      }
    this.initVerify(certificate.getPublicKey());
  }

  /**
   * Initialize this object for signing. If this method is called again with a
   * different argument, it negates the effect of this call.
   *
   * @param privateKey the private key of the identity whose signature is going
   * to be generated.
   * @throws InvalidKeyException if the key is invalid.
   */
  public final void initSign(PrivateKey privateKey) throws InvalidKeyException
  {
    state = SIGN;
    engineInitSign(privateKey);
  }

  /**
   * Initialize this object for signing. If this method is called again with a
   * different argument, it negates the effect of this call.
   *
   * @param privateKey the private key of the identity whose signature is going
   * to be generated.
   * @param random the source of randomness for this signature.
   * @throws InvalidKeyException if the key is invalid.
   */
  public final void initSign(PrivateKey privateKey, SecureRandom random)
    throws InvalidKeyException
  {
    state = SIGN;
    engineInitSign(privateKey, random);
  }

  /**
   * <p>Returns the signature bytes of all the data updated. The format of the
   * signature depends on the underlying signature scheme.</p>
   *
   * <p>A call to this method resets this signature object to the state it was
   * in when previously initialized for signing via a call to
   * <code>initSign(PrivateKey)</code>. That is, the object is reset and
   * available to generate another signature from the same signer, if desired,
   * via new calls to <code>update()</code> and <code>sign()</code>.</p>
   *
   * @return the signature bytes of the signing operation's result.
   * @throws SignatureException if this signature object is not initialized
   * properly.
   */
  public final byte[] sign() throws SignatureException
  {
    if (state == SIGN)
      return engineSign();
    else
      throw new SignatureException();
  }

  /**
   * <p>Finishes the signature operation and stores the resulting signature
   * bytes in the provided buffer <code>outbuf</code>, starting at <code>offset
   * </code>. The format of the signature depends on the underlying signature
   * scheme.</p>
   *
   * <p>This signature object is reset to its initial state (the state it was
   * in after a call to one of the <code>initSign()</code> methods) and can be
   * reused to generate further signatures with the same private key.</p>
   *
   * @param outbuf buffer for the signature result.
   * @param offset offset into outbuf where the signature is stored.
   * @param len number of bytes within outbuf allotted for the signature.
   * @return the number of bytes placed into outbuf.
   * @throws SignatureException if an error occurs or len is less than the
   * actual signature length.
   * @since 1.2
   */
  public final int sign(byte[] outbuf, int offset, int len)
    throws SignatureException
  {
    if (state == SIGN)
      return engineSign(outbuf, offset, len);
    else
      throw new SignatureException();
  }

  /**
   * <p>Verifies the passed-in signature.</p>
   *
   * <p>A call to this method resets this signature object to the state it was
   * in when previously initialized for verification via a call to
   * <code>initVerify(PublicKey)</code>. That is, the object is reset and
   * available to verify another signature from the identity whose public key
   * was specified in the call to <code>initVerify()</code>.</p>
   *
   * @param signature the signature bytes to be verified.
   * @return <code>true</code> if the signature was verified, <code>false</code>
   * if not.
   * @throws SignatureException if this signature object is not initialized
   * properly, or the passed-in signature is improperly encoded or of the wrong
   * type, etc.
   */
  public final boolean verify(byte[]signature) throws SignatureException
  {
    if (state == VERIFY)
      return engineVerify(signature);
    else
      throw new SignatureException();
  }

  /**
   * <p>Verifies the passed-in <code>signature</code> in the specified array of
   * bytes, starting at the specified <code>offset</code>.</p>
   *
   * <p>A call to this method resets this signature object to the state it was
   * in when previously initialized for verification via a call to
   * <code>initVerify(PublicKey)</code>. That is, the object is reset and
   * available to verify another signature from the identity whose public key
   * was specified in the call to <code>initVerify()</code>.</p>
   *
   * @param signature the signature bytes to be verified.
   * @param offset the offset to start from in the array of bytes.
   * @param length the number of bytes to use, starting at offset.
   * @return <code>true</code> if the signature was verified, <code>false</code>
   * if not.
   * @throws SignatureException if this signature object is not initialized
   * properly, or the passed-in <code>signature</code> is improperly encoded or
   * of the wrong type, etc.
   * @throws IllegalArgumentException if the <code>signature</code> byte array
   * is <code>null</code>, or the <code>offset</code> or <code>length</code> is
   * less than <code>0</code>, or the sum of the <code>offset</code> and
   * <code>length</code> is greater than the length of the <code>signature</code>
   * byte array.
   */
  public final boolean verify(byte[] signature, int offset, int length)
    throws SignatureException
  {
    if (state != VERIFY)
      throw new SignatureException("illegal state");

    if (signature == null)
      throw new IllegalArgumentException("signature is null");
    if (offset < 0)
      throw new IllegalArgumentException("offset is less than 0");
    if (length < 0)
      throw new IllegalArgumentException("length is less than 0");
    if (offset + length < signature.length)
      throw new IllegalArgumentException("range is out of bounds");

    return engineVerify(signature, offset, length);
  }

  /**
   * Updates the data to be signed or verified by a byte.
   *
   * @param b the byte to use for the update.
   * @throws SignatureException if this signature object is not initialized
   * properly.
   */
  public final void update(byte b) throws SignatureException
  {
    if (state != UNINITIALIZED)
      engineUpdate(b);
    else
      throw new SignatureException();
  }

  /**
   * Updates the data to be signed or verified, using the specified array of
   * bytes.
   *
   * @param data the byte array to use for the update.
   * @throws SignatureException if this signature object is not initialized
   * properly.
   */
  public final void update(byte[]data) throws SignatureException
  {
    if (state != UNINITIALIZED)
      engineUpdate(data, 0, data.length);
    else
      throw new SignatureException();
  }

  /**
   * Updates the data to be signed or verified, using the specified array of
   * bytes, starting at the specified offset.
   *
   * @param data the array of bytes.
   * @param off the offset to start from in the array of bytes.
   * @param len the number of bytes to use, starting at offset.
   * @throws SignatureException if this signature object is not initialized
   * properly.
   */
  public final void update(byte[]data, int off, int len)
    throws SignatureException
  {
    if (state != UNINITIALIZED)
      engineUpdate(data, off, len);
    else
      throw new SignatureException();
  }

  /**
   * Returns the name of the algorithm for this signature object.
   *
   * @return the name of the algorithm for this signature object.
   */
  public final String getAlgorithm()
  {
    return algorithm;
  }

  /**
   * Returns a string representation of this signature object, providing
   * information that includes the state of the object and the name of the
   * algorithm used.
   *
   * @return a string representation of this signature object.
   */
  public String toString()
  {
    return (algorithm + " Signature");
  }

  /**
   * Sets the specified algorithm parameter to the specified value. This method
   * supplies a general-purpose mechanism through which it is possible to set
   * the various parameters of this object. A parameter may be any settable
   * parameter for the algorithm, such as a parameter size, or a source of
   * random bits for signature generation (if appropriate), or an indication of
   * whether or not to perform a specific but optional computation. A uniform
   * algorithm-specific naming scheme for each parameter is desirable but left
   * unspecified at this time.
   *
   * @param param the string identifier of the parameter.
   * @param value the parameter value.
   * @throws InvalidParameterException if param is an invalid parameter for this
   * signature algorithm engine, the parameter is already set and cannot be set
   * again, a security exception occurs, and so on.
   * @see #getParameter(String)
   * @deprecated Use setParameter(AlgorithmParameterSpec).
   */
  public final void setParameter(String param, Object value)
    throws InvalidParameterException
  {
    engineSetParameter(param, value);
  }

  /**
   * Initializes this signature engine with the specified parameter set.
   *
   * @param params the parameters.
   * @throws InvalidAlgorithmParameterException if the given parameters are
   * inappropriate for this signature engine.
   * @see #getParameters()
   */
  public final void setParameter(AlgorithmParameterSpec params)
    throws InvalidAlgorithmParameterException
  {
    engineSetParameter(params);
  }

  /**
   * <p>Returns the parameters used with this signature object.</p>
   *
   * <p>The returned parameters may be the same that were used to initialize
   * this signature, or may contain a combination of default and randomly
   * generated parameter values used by the underlying signature implementation
   * if this signature requires algorithm parameters but was not initialized
   * with any.
   *
   * @return the parameters used with this signature, or <code>null</code> if
   * this signature does not use any parameters.
   * @see #setParameter(AlgorithmParameterSpec)
   */
  public final AlgorithmParameters getParameters()
  {
    return engineGetParameters();
  }

  /**
   * Gets the value of the specified algorithm parameter. This method supplies
   * a general-purpose mechanism through which it is possible to get the various
   * parameters of this object. A parameter may be any settable parameter for
   * the algorithm, such as a parameter size, or a source of random bits for
   * signature generation (if appropriate), or an indication of whether or not
   * to perform a specific but optional computation. A uniform
   * algorithm-specific naming scheme for each parameter is desirable but left
   * unspecified at this time.
   *
   * @param param the string name of the parameter.
   * @return the object that represents the parameter value, or null if there
   * is none.
   * @throws InvalidParameterException if param is an invalid parameter for this
   * engine, or another exception occurs while trying to get this parameter.
   * @see #setParameter(String, Object)
   * @deprecated
   */
  public final Object getParameter(String param)
    throws InvalidParameterException
  {
    return engineGetParameter(param);
  }

  /**
   * Returns a clone if the implementation is cloneable.
   *
   * @return a clone if the implementation is cloneable.
   * @throws CloneNotSupportedException if this is called on an implementation
   * that does not support {@link Cloneable}.
   */
  public Object clone() throws CloneNotSupportedException
  {
    return super.clone();
  }
}
