- /*
- * @(#)Signature.java 1.85 00/02/02
- *
- * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the proprietary information of Sun Microsystems, Inc.
- * Use is subject to license terms.
- *
- */
-
- package java.security;
-
- import java.security.spec.AlgorithmParameterSpec;
- import java.util.*;
- import java.io.*;
- import java.security.cert.Certificate;
- import java.security.cert.X509Certificate;
-
- /**
- * This Signature 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> The signature algorithm can be, among others, the NIST standard
- * DSA, using DSA and SHA-1. The DSA algorithm using the
- * SHA-1 message digest algorithm can be specified as <tt>SHA1withDSA</tt>.
- * In the case of RSA, there are multiple choices for the message digest
- * algorithm, so the signing algorithm could be specified as, for example,
- * <tt>MD2withRSA</tt>, <tt>MD5withRSA</tt>, or <tt>SHA1withRSA</tt>.
- * The algorithm name must be specified, as there is no default.
- *
- * <p>Like other algorithm-based classes in Java Security, Signature
- * provides implementation-independent algorithms, whereby a caller
- * (application code) requests a particular signature algorithm
- * and is handed back a properly initialized Signature object. It is
- * also possible, if desired, to request a particular algorithm from a
- * particular provider. See the <code>getInstance </code> methods.
- *
- * <p>Thus, there are two ways to request a Signature algorithm object: by
- * specifying either just an algorithm name, or both an algorithm name
- * and a package provider. <ul>
- *
- * <li>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>
- *
- * <li>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.
- *
- * </ul>
- *
- * <p>A Signature object can be used to generate and verify digital
- * signatures.
- *
- * <p>There are three phases to the use of a Signature object for
- * either signing data or verifying a signature:<ol>
- *
- * <li>Initialization, with either
- *
- * <ul>
- *
- * <li>a public key, which initializes the signature for
- * verification (see {@link #initVerify(PublicKey) initVerify}), or
- *
- * <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)}).
- *
- * </ul><p>
- *
- * <li>Updating<p>
- *
- * <p>Depending on the type of initialization, this will update the
- * bytes to be signed or verified. See the
- * {@link #update(byte) update} methods.<p>
- *
- * <li>Signing or Verifying a signature on all updated bytes. See the
- * {@link #sign() sign} methods and the {@link #verify(byte[]) verify}
- * method.
- *
- * </ol>
- *
- * <p>Note that this class is abstract and extends from
- * <code>SignatureSpi</code> 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 Benjamin Renaud
- *
- * @version 1.85, 02/02/00
- */
-
- public abstract class Signature extends SignatureSpi {
-
- /* Are we in debugging mode? */
- private static final boolean debug = false;
-
- /*
- * The algorithm for this signature object.
- * This value is used to map an OID to the particular algorithm.
- * The mapping is done in AlgorithmObject.algOID(String algorithm)
- */
- private String algorithm;
-
- // The provider
- private Provider provider;
-
- /**
- * Possible {@link #state} value, signifying that
- * this signature object has not yet been initialized.
- */
- protected final static int UNINITIALIZED = 0;
-
- /**
- * Possible {@link #state} value, signifying that
- * this signature object has been initialized for signing.
- */
- protected final static int SIGN = 2;
-
- /**
- * Possible {@link #state} value, signifying that
- * this signature object has been initialized for verification.
- */
- protected final static int VERIFY = 3;
-
- /**
- * Current state of this signature object.
- */
- protected int state = UNINITIALIZED;
-
- /**
- * Creates a Signature object for the specified algorithm.
- *
- * @param algorithm the standard string name of the algorithm.
- * See Appendix A in the <a href=
- * "../../../guide/security/CryptoSpec.html#AppA">
- * Java Cryptography Architecture API Specification & Reference </a>
- * for information about standard algorithm names.
- */
- protected Signature(String algorithm) {
- this.algorithm = algorithm;
- }
-
- /**
- * Generates a Signature object that implements the specified digest
- * algorithm. If the default provider package
- * provides an implementation of the requested digest algorithm,
- * an instance of Signature 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 <a href=
- * "../../../guide/security/CryptoSpec.html#AppA">
- * Java Cryptography Architecture API Specification & Reference </a>
- * for information about standard algorithm names.
- *
- * @return the new Signature object.
- *
- * @exception NoSuchAlgorithmException if the algorithm is
- * not available in the environment.
- */
- public static Signature getInstance(String algorithm)
- throws NoSuchAlgorithmException {
- try {
- Object[] objs = Security.getImpl(algorithm, "Signature", null);
- if (objs[0] instanceof Signature) {
- Signature sig = (Signature)objs[0];
- sig.provider = (Provider)objs[1];
- return sig;
- } else {
- Signature delegate =
- new Delegate((SignatureSpi)objs[0], algorithm);
- delegate.provider = (Provider)objs[1];
- return delegate;
- }
- } catch(NoSuchProviderException e) {
- throw new NoSuchAlgorithmException(algorithm + " not found");
- }
- }
-
- /**
- * Generates a Signature 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 <a href=
- * "../../../guide/security/CryptoSpec.html#AppA">
- * Java Cryptography Architecture API Specification & Reference </a>
- * for information about standard algorithm names.
- *
- * @param provider the name of the provider.
- *
- * @return the new Signature object.
- *
- * @exception NoSuchAlgorithmException if the algorithm is
- * not available in the package supplied by the requested
- * provider.
- *
- * @exception NoSuchProviderException if the provider is not
- * available in the environment.
- *
- * @see Provider
- */
- public static Signature getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
- {
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("missing provider");
- Object[] objs = Security.getImpl(algorithm, "Signature", provider);
- if (objs[0] instanceof Signature) {
- Signature sig = (Signature)objs[0];
- sig.provider = (Provider)objs[1];
- return sig;
- } else {
- Signature delegate =
- new Delegate((SignatureSpi)objs[0], algorithm);
- delegate.provider = (Provider)objs[1];
- return delegate;
- }
- }
-
- /**
- * Returns the provider of this signature object.
- *
- * @return the provider of this signature object
- */
- public final Provider getProvider() {
- return this.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.
- *
- * @exception InvalidKeyException if the key is invalid.
- */
- public final void initVerify(PublicKey publicKey)
- throws InvalidKeyException {
- engineInitVerify(publicKey);
- state = VERIFY;
- }
-
- /**
- * Initializes this object for verification, using the public key from
- * the given certificate.
- * <p>If the certificate is of type X.509 and has a <i>key usage</i>
- * extension field marked as critical, 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 <code>InvalidKeyException</code>
- * is thrown.
- *
- * @param certificate the certificate of the identity whose signature is
- * going to be verified.
- *
- * @exception 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 {
- // If the certificate is of type X509Certificate,
- // we should check whether it has a Key Usage
- // extension marked as critical.
- if (certificate instanceof java.security.cert.X509Certificate) {
- // Check whether the cert has a key usage extension
- // marked as a critical extension.
- // The OID for KeyUsage extension is 2.5.29.15.
- X509Certificate cert = (X509Certificate)certificate;
- Set critSet = cert.getCriticalExtensionOIDs();
-
- if (critSet != null && !critSet.isEmpty()
- && critSet.contains(new String("2.5.29.15"))) {
- boolean[] keyUsageInfo = cert.getKeyUsage();
- // keyUsageInfo[0] is for digitalSignature.
- if ((keyUsageInfo != null) && (keyUsageInfo[0] == false))
- throw new InvalidKeyException("Wrong key usage");
- }
- }
-
- PublicKey publicKey = certificate.getPublicKey();
- engineInitVerify(publicKey);
- state = VERIFY;
- }
-
- /**
- * 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.
- *
- * @exception InvalidKeyException if the key is invalid.
- */
- public final void initSign(PrivateKey privateKey)
- throws InvalidKeyException {
- engineInitSign(privateKey);
- state = SIGN;
- }
-
- /**
- * 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.
- *
- * @exception InvalidKeyException if the key is invalid.
- */
- public final void initSign(PrivateKey privateKey, SecureRandom random)
- throws InvalidKeyException {
- engineInitSign(privateKey, random);
- state = SIGN;
- }
-
- /**
- * Returns the signature bytes of all the data updated.
- * The format of the signature depends on the underlying
- * signature scheme.
- *
- * <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>.
- *
- * @return the signature bytes of the signing operation's result.
- *
- * @exception SignatureException if this signature object is not
- * initialized properly.
- */
- public final byte[] sign() throws SignatureException {
- if (state == SIGN) {
- return engineSign();
- }
- throw new SignatureException("object not initialized for " +
- "signing");
- }
-
- /**
- * 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>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.
- *
- * @param outbuf buffer for the signature result.
- *
- * @param offset offset into <code>outbuf</code> where the signature is
- * stored.
- *
- * @param len number of bytes within <code>outbuf</code> allotted for the
- * signature.
- *
- * @return the number of bytes placed into <code>outbuf</code>.
- *
- * @exception SignatureException if an error occurs or <code>len</code>
- * is less than the actual signature length.
- *
- * @since 1.2
- */
- public final int sign(byte[] outbuf, int offset, int len)
- throws SignatureException {
- if (outbuf == null) {
- throw new IllegalArgumentException("No output buffer given");
- }
- if (outbuf.length - offset < len) {
- throw new IllegalArgumentException
- ("Output buffer too small for specified offset and length");
- }
- if (state != SIGN) {
- throw new SignatureException("object not initialized for " +
- "signing");
- }
- return engineSign(outbuf, offset, len);
- }
-
- /**
- * Verifies the passed-in signature.
- *
- * <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>.
- *
- * @param signature the signature bytes to be verified.
- *
- * @return true if the signature was verified, false if not.
- *
- * @exception 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);
- }
- throw new SignatureException("object not initialized for " +
- "verification");
- }
-
- /**
- * Updates the data to be signed or verified by a byte.
- *
- * @param b the byte to use for the update.
- *
- * @exception SignatureException if this signature object is not
- * initialized properly.
- */
- public final void update(byte b) throws SignatureException {
- if (state == VERIFY || state == SIGN) {
- engineUpdate(b);
- } else {
- throw new SignatureException("object not initialized for "
- + "signature or verification");
- }
- }
-
- /**
- * Updates the data to be signed or verified, using the specified
- * array of bytes.
- *
- * @param data the byte array to use for the update.
- *
- * @exception SignatureException if this signature object is not
- * initialized properly.
- */
- public final void update(byte[] data) throws SignatureException {
- update(data, 0, data.length);
- }
-
- /**
- * 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.
- *
- * @exception SignatureException if this signature object is not
- * initialized properly.
- */
- public final void update(byte[] data, int off, int len)
- throws SignatureException {
- if (state == SIGN || state == VERIFY) {
- engineUpdate(data, off, len);
- } else {
- throw new SignatureException("object not initialized for "
- + "signature or verification");
- }
- }
-
- /**
- * 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 this.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() {
- String initState = "";
- switch (state) {
- case UNINITIALIZED:
- initState = "<not initialized>";
- break;
- case VERIFY:
- initState = "<initialized for verifying>";
- break;
- case SIGN:
- initState = "<initialized for signing>";
- break;
- }
- return "Signature object: " + getAlgorithm() + initState;
- }
-
- /**
- * 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.
- *
- * @exception InvalidParameterException if <code>param</code> 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.
- *
- * @deprecated Use
- * {@link #setParameter(java.security.spec.AlgorithmParameterSpec)
- * setParameter}.
- */
- 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
- *
- * @exception InvalidAlgorithmParameterException if the given parameters
- * are inappropriate for this signature engine
- */
- public final void setParameter(AlgorithmParameterSpec params)
- throws InvalidAlgorithmParameterException {
- engineSetParameter(params);
- }
-
- /**
- * 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.
- *
- * @exception InvalidParameterException if <code>param</code> is an invalid
- * parameter for this engine, or another exception occurs while
- * trying to get this parameter.
- *
- * @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.
- *
- * @exception CloneNotSupportedException if this is called
- * on an implementation that does not support <code>Cloneable</code>.
- */
- public Object clone() throws CloneNotSupportedException {
- if (this instanceof Cloneable) {
- return super.clone();
- } else {
- throw new CloneNotSupportedException();
- }
- }
-
- // private debugging method.
- private static void debug(String statement) {
- if (debug) {
- System.err.println(statement);
- }
- }
-
- // private debugging method.
- private static void debug(Exception e) {
- if (debug) {
- e.printStackTrace();
- }
- }
-
-
-
-
- /*
- * The following class allows providers to extend from SignatureSpi
- * rather than from Signature. It represents a Signature with an
- * encapsulated, provider-supplied SPI object (of type SignatureSpi).
- * If the provider implementation is an instance of SignatureSpi, the
- * getInstance() methods above return an instance of this class, with
- * the SPI object encapsulated.
- *
- * Note: All SPI methods from the original Signature class have been
- * moved up the hierarchy into a new class (SignatureSpi), which has
- * been interposed in the hierarchy between the API (Signature)
- * and its original parent (Object).
- */
-
- static class Delegate extends Signature {
-
- // The provider implementation (delegate)
- private SignatureSpi sigSpi;
-
- // constructor
- public Delegate(SignatureSpi sigSpi, String algorithm) {
- super(algorithm);
- this.sigSpi = sigSpi;
- }
-
- /*
- * Returns a clone if the delegate is cloneable.
- *
- * @return a clone if the delegate is cloneable.
- *
- * @exception CloneNotSupportedException if this is called on a
- * delegate that does not support <code>Cloneable</code>.
- */
- public Object clone() throws CloneNotSupportedException {
- if (sigSpi instanceof Cloneable) {
- SignatureSpi sigSpiClone = (SignatureSpi)sigSpi.clone();
- // Because 'algorithm' and 'provider' are private
- // members of our supertype, we must perform a cast to
- // access them.
- Signature that =
- new Delegate(sigSpiClone, ((Signature)this).algorithm);
- that.provider = ((Signature)this).provider;
- return that;
- } else {
- throw new CloneNotSupportedException();
- }
- }
-
- protected void engineInitVerify(PublicKey publicKey)
- throws InvalidKeyException {
- sigSpi.engineInitVerify(publicKey);
- }
-
- protected void engineInitSign(PrivateKey privateKey)
- throws InvalidKeyException {
- sigSpi.engineInitSign(privateKey);
- }
-
- protected void engineUpdate(byte b) throws SignatureException {
- sigSpi.engineUpdate(b);
- }
-
- protected void engineUpdate(byte[] b, int off, int len)
- throws SignatureException {
- sigSpi.engineUpdate(b, off, len);
- }
-
- protected byte[] engineSign() throws SignatureException {
- return sigSpi.engineSign();
- }
-
- protected int engineSign(byte[] outbuf, int offset, int len)
- throws SignatureException {
- return sigSpi.engineSign(outbuf, offset, len);
- }
-
- protected boolean engineVerify(byte[] sigBytes)
- throws SignatureException {
- return sigSpi.engineVerify(sigBytes);
- }
-
- protected void engineSetParameter(String param, Object value)
- throws InvalidParameterException {
- sigSpi.engineSetParameter(param, value);
- }
-
- protected void engineSetParameter(AlgorithmParameterSpec params)
- throws InvalidAlgorithmParameterException {
- sigSpi.engineSetParameter(params);
- }
-
- protected Object engineGetParameter(String param)
- throws InvalidParameterException {
- return sigSpi.engineGetParameter(param);
- }
- }
- }
-
-
-
-
-
-
-
-