Save This Page
Home » openjdk-7 » java » security » [javadoc | source]
    1   /*
    2    * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.security;
   27   
   28   import java.security.spec.AlgorithmParameterSpec;
   29   import java.util;
   30   import java.util.concurrent.ConcurrentHashMap;
   31   import java.io;
   32   import java.security.cert.Certificate;
   33   import java.security.cert.X509Certificate;
   34   
   35   import java.nio.ByteBuffer;
   36   
   37   import java.security.Provider.Service;
   38   
   39   import javax.crypto.Cipher;
   40   import javax.crypto.CipherSpi;
   41   import javax.crypto.IllegalBlockSizeException;
   42   import javax.crypto.BadPaddingException;
   43   import javax.crypto.NoSuchPaddingException;
   44   
   45   import sun.security.util.Debug;
   46   import sun.security.jca;
   47   import sun.security.jca.GetInstance.Instance;
   48   
   49   /**
   50    * This Signature class is used to provide applications the functionality
   51    * of a digital signature algorithm. Digital signatures are used for
   52    * authentication and integrity assurance of digital data.
   53    *
   54    * <p> The signature algorithm can be, among others, the NIST standard
   55    * DSA, using DSA and SHA-1. The DSA algorithm using the
   56    * SHA-1 message digest algorithm can be specified as <tt>SHA1withDSA</tt>.
   57    * In the case of RSA, there are multiple choices for the message digest
   58    * algorithm, so the signing algorithm could be specified as, for example,
   59    * <tt>MD2withRSA</tt>, <tt>MD5withRSA</tt>, or <tt>SHA1withRSA</tt>.
   60    * The algorithm name must be specified, as there is no default.
   61    *
   62    * <p> A Signature object can be used to generate and verify digital
   63    * signatures.
   64    *
   65    * <p> There are three phases to the use of a Signature object for
   66    * either signing data or verifying a signature:<ol>
   67    *
   68    * <li>Initialization, with either
   69    *
   70    *     <ul>
   71    *
   72    *     <li>a public key, which initializes the signature for
   73    *     verification (see {@link #initVerify(PublicKey) initVerify}), or
   74    *
   75    *     <li>a private key (and optionally a Secure Random Number Generator),
   76    *     which initializes the signature for signing
   77    *     (see {@link #initSign(PrivateKey)}
   78    *     and {@link #initSign(PrivateKey, SecureRandom)}).
   79    *
   80    *     </ul><p>
   81    *
   82    * <li>Updating<p>
   83    *
   84    * <p>Depending on the type of initialization, this will update the
   85    * bytes to be signed or verified. See the
   86    * {@link #update(byte) update} methods.<p>
   87    *
   88    * <li>Signing or Verifying a signature on all updated bytes. See the
   89    * {@link #sign() sign} methods and the {@link #verify(byte[]) verify}
   90    * method.
   91    *
   92    * </ol>
   93    *
   94    * <p>Note that this class is abstract and extends from
   95    * <code>SignatureSpi</code> for historical reasons.
   96    * Application developers should only take notice of the methods defined in
   97    * this <code>Signature</code> class; all the methods in
   98    * the superclass are intended for cryptographic service providers who wish to
   99    * supply their own implementations of digital signature algorithms.
  100    *
  101    * @author Benjamin Renaud
  102    *
  103    */
  104   
  105   public abstract class Signature extends SignatureSpi {
  106   
  107       private static final Debug debug =
  108                           Debug.getInstance("jca", "Signature");
  109   
  110       /*
  111        * The algorithm for this signature object.
  112        * This value is used to map an OID to the particular algorithm.
  113        * The mapping is done in AlgorithmObject.algOID(String algorithm)
  114        */
  115       private String algorithm;
  116   
  117       // The provider
  118       Provider provider;
  119   
  120       /**
  121        * Possible {@link #state} value, signifying that
  122        * this signature object has not yet been initialized.
  123        */
  124       protected final static int UNINITIALIZED = 0;
  125   
  126       /**
  127        * Possible {@link #state} value, signifying that
  128        * this signature object has been initialized for signing.
  129        */
  130       protected final static int SIGN = 2;
  131   
  132       /**
  133        * Possible {@link #state} value, signifying that
  134        * this signature object has been initialized for verification.
  135        */
  136       protected final static int VERIFY = 3;
  137   
  138       /**
  139        * Current state of this signature object.
  140        */
  141       protected int state = UNINITIALIZED;
  142   
  143       /**
  144        * Creates a Signature object for the specified algorithm.
  145        *
  146        * @param algorithm the standard string name of the algorithm.
  147        * See Appendix A in the <a href=
  148        * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
  149        * Java Cryptography Architecture API Specification &amp; Reference </a>
  150        * for information about standard algorithm names.
  151        */
  152       protected Signature(String algorithm) {
  153           this.algorithm = algorithm;
  154       }
  155   
  156       // name of the special signature alg
  157       private final static String RSA_SIGNATURE = "NONEwithRSA";
  158   
  159       // name of the equivalent cipher alg
  160       private final static String RSA_CIPHER = "RSA/ECB/PKCS1Padding";
  161   
  162       // all the services we need to lookup for compatibility with Cipher
  163       private final static List<ServiceId> rsaIds = Arrays.asList(
  164           new ServiceId[] {
  165               new ServiceId("Signature", "NONEwithRSA"),
  166               new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"),
  167               new ServiceId("Cipher", "RSA/ECB"),
  168               new ServiceId("Cipher", "RSA//PKCS1Padding"),
  169               new ServiceId("Cipher", "RSA"),
  170           }
  171       );
  172   
  173       /**
  174        * Returns a Signature object that implements the specified signature
  175        * algorithm.
  176        *
  177        * <p> This method traverses the list of registered security Providers,
  178        * starting with the most preferred Provider.
  179        * A new Signature object encapsulating the
  180        * SignatureSpi implementation from the first
  181        * Provider that supports the specified algorithm is returned.
  182        *
  183        * <p> Note that the list of registered providers may be retrieved via
  184        * the {@link Security#getProviders() Security.getProviders()} method.
  185        *
  186        * @param algorithm the standard name of the algorithm requested.
  187        * See Appendix A in the <a href=
  188        * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
  189        * Java Cryptography Architecture API Specification &amp; Reference </a>
  190        * for information about standard algorithm names.
  191        *
  192        * @return the new Signature object.
  193        *
  194        * @exception NoSuchAlgorithmException if no Provider supports a
  195        *          Signature implementation for the
  196        *          specified algorithm.
  197        *
  198        * @see Provider
  199        */
  200       public static Signature getInstance(String algorithm)
  201               throws NoSuchAlgorithmException {
  202           List<Service> list;
  203           if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
  204               list = GetInstance.getServices(rsaIds);
  205           } else {
  206               list = GetInstance.getServices("Signature", algorithm);
  207           }
  208           Iterator<Service> t = list.iterator();
  209           if (t.hasNext() == false) {
  210               throw new NoSuchAlgorithmException
  211                   (algorithm + " Signature not available");
  212           }
  213           // try services until we find an Spi or a working Signature subclass
  214           NoSuchAlgorithmException failure;
  215           do {
  216               Service s = t.next();
  217               if (isSpi(s)) {
  218                   return new Delegate(s, t, algorithm);
  219               } else {
  220                   // must be a subclass of Signature, disable dynamic selection
  221                   try {
  222                       Instance instance =
  223                           GetInstance.getInstance(s, SignatureSpi.class);
  224                       return getInstance(instance, algorithm);
  225                   } catch (NoSuchAlgorithmException e) {
  226                       failure = e;
  227                   }
  228               }
  229           } while (t.hasNext());
  230           throw failure;
  231       }
  232   
  233       private static Signature getInstance(Instance instance, String algorithm) {
  234           Signature sig;
  235           if (instance.impl instanceof Signature) {
  236               sig = (Signature)instance.impl;
  237           } else {
  238               SignatureSpi spi = (SignatureSpi)instance.impl;
  239               sig = new Delegate(spi, algorithm);
  240           }
  241           sig.provider = instance.provider;
  242           return sig;
  243       }
  244   
  245       private final static Map<String,Boolean> signatureInfo;
  246   
  247       static {
  248           signatureInfo = new ConcurrentHashMap<String,Boolean>();
  249           Boolean TRUE = Boolean.TRUE;
  250           // pre-initialize with values for our SignatureSpi implementations
  251           signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE);
  252           signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE);
  253           signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE);
  254           signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE);
  255           signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE);
  256           signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE);
  257           signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE);
  258           signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE);
  259           signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE);
  260           signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE);
  261       }
  262   
  263       private static boolean isSpi(Service s) {
  264           if (s.getType().equals("Cipher")) {
  265               // must be a CipherSpi, which we can wrap with the CipherAdapter
  266               return true;
  267           }
  268           String className = s.getClassName();
  269           Boolean result = signatureInfo.get(className);
  270           if (result == null) {
  271               try {
  272                   Object instance = s.newInstance(null);
  273                   // Signature extends SignatureSpi
  274                   // so it is a "real" Spi if it is an
  275                   // instance of SignatureSpi but not Signature
  276                   boolean r = (instance instanceof SignatureSpi)
  277                                   && (instance instanceof Signature == false);
  278                   if ((debug != null) && (r == false)) {
  279                       debug.println("Not a SignatureSpi " + className);
  280                       debug.println("Delayed provider selection may not be "
  281                           + "available for algorithm " + s.getAlgorithm());
  282                   }
  283                   result = Boolean.valueOf(r);
  284                   signatureInfo.put(className, result);
  285               } catch (Exception e) {
  286                   // something is wrong, assume not an SPI
  287                   return false;
  288               }
  289           }
  290           return result.booleanValue();
  291       }
  292   
  293       /**
  294        * Returns a Signature object that implements the specified signature
  295        * algorithm.
  296        *
  297        * <p> A new Signature object encapsulating the
  298        * SignatureSpi implementation from the specified provider
  299        * is returned.  The specified provider must be registered
  300        * in the security provider list.
  301        *
  302        * <p> Note that the list of registered providers may be retrieved via
  303        * the {@link Security#getProviders() Security.getProviders()} method.
  304        *
  305        * @param algorithm the name of the algorithm requested.
  306        * See Appendix A in the <a href=
  307        * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
  308        * Java Cryptography Architecture API Specification &amp; Reference </a>
  309        * for information about standard algorithm names.
  310        *
  311        * @param provider the name of the provider.
  312        *
  313        * @return the new Signature object.
  314        *
  315        * @exception NoSuchAlgorithmException if a SignatureSpi
  316        *          implementation for the specified algorithm is not
  317        *          available from the specified provider.
  318        *
  319        * @exception NoSuchProviderException if the specified provider is not
  320        *          registered in the security provider list.
  321        *
  322        * @exception IllegalArgumentException if the provider name is null
  323        *          or empty.
  324        *
  325        * @see Provider
  326        */
  327       public static Signature getInstance(String algorithm, String provider)
  328               throws NoSuchAlgorithmException, NoSuchProviderException {
  329           if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
  330               // exception compatibility with existing code
  331               if ((provider == null) || (provider.length() == 0)) {
  332                   throw new IllegalArgumentException("missing provider");
  333               }
  334               Provider p = Security.getProvider(provider);
  335               if (p == null) {
  336                   throw new NoSuchProviderException
  337                       ("no such provider: " + provider);
  338               }
  339               return getInstanceRSA(p);
  340           }
  341           Instance instance = GetInstance.getInstance
  342                   ("Signature", SignatureSpi.class, algorithm, provider);
  343           return getInstance(instance, algorithm);
  344       }
  345   
  346       /**
  347        * Returns a Signature object that implements the specified
  348        * signature algorithm.
  349        *
  350        * <p> A new Signature object encapsulating the
  351        * SignatureSpi implementation from the specified Provider
  352        * object is returned.  Note that the specified Provider object
  353        * does not have to be registered in the provider list.
  354        *
  355        * @param algorithm the name of the algorithm requested.
  356        * See Appendix A in the <a href=
  357        * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
  358        * Java Cryptography Architecture API Specification &amp; Reference </a>
  359        * for information about standard algorithm names.
  360        *
  361        * @param provider the provider.
  362        *
  363        * @return the new Signature object.
  364        *
  365        * @exception NoSuchAlgorithmException if a SignatureSpi
  366        *          implementation for the specified algorithm is not available
  367        *          from the specified Provider object.
  368        *
  369        * @exception IllegalArgumentException if the provider is null.
  370        *
  371        * @see Provider
  372        *
  373        * @since 1.4
  374        */
  375       public static Signature getInstance(String algorithm, Provider provider)
  376               throws NoSuchAlgorithmException {
  377           if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
  378               // exception compatibility with existing code
  379               if (provider == null) {
  380                   throw new IllegalArgumentException("missing provider");
  381               }
  382               return getInstanceRSA(provider);
  383           }
  384           Instance instance = GetInstance.getInstance
  385                   ("Signature", SignatureSpi.class, algorithm, provider);
  386           return getInstance(instance, algorithm);
  387       }
  388   
  389       // return an implementation for NONEwithRSA, which is a special case
  390       // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper
  391       private static Signature getInstanceRSA(Provider p)
  392               throws NoSuchAlgorithmException {
  393           // try Signature first
  394           Service s = p.getService("Signature", RSA_SIGNATURE);
  395           if (s != null) {
  396               Instance instance = GetInstance.getInstance(s, SignatureSpi.class);
  397               return getInstance(instance, RSA_SIGNATURE);
  398           }
  399           // check Cipher
  400           try {
  401               Cipher c = Cipher.getInstance(RSA_CIPHER, p);
  402               return new Delegate(new CipherAdapter(c), RSA_SIGNATURE);
  403           } catch (GeneralSecurityException e) {
  404               // throw Signature style exception message to avoid confusion,
  405               // but append Cipher exception as cause
  406               throw new NoSuchAlgorithmException("no such algorithm: "
  407                   + RSA_SIGNATURE + " for provider " + p.getName(), e);
  408           }
  409       }
  410   
  411       /**
  412        * Returns the provider of this signature object.
  413        *
  414        * @return the provider of this signature object
  415        */
  416       public final Provider getProvider() {
  417           chooseFirstProvider();
  418           return this.provider;
  419       }
  420   
  421       void chooseFirstProvider() {
  422           // empty, overridden in Delegate
  423       }
  424   
  425       /**
  426        * Initializes this object for verification. If this method is called
  427        * again with a different argument, it negates the effect
  428        * of this call.
  429        *
  430        * @param publicKey the public key of the identity whose signature is
  431        * going to be verified.
  432        *
  433        * @exception InvalidKeyException if the key is invalid.
  434        */
  435       public final void initVerify(PublicKey publicKey)
  436               throws InvalidKeyException {
  437           engineInitVerify(publicKey);
  438           state = VERIFY;
  439       }
  440   
  441       /**
  442        * Initializes this object for verification, using the public key from
  443        * the given certificate.
  444        * <p>If the certificate is of type X.509 and has a <i>key usage</i>
  445        * extension field marked as critical, and the value of the <i>key usage</i>
  446        * extension field implies that the public key in
  447        * the certificate and its corresponding private key are not
  448        * supposed to be used for digital signatures, an
  449        * <code>InvalidKeyException</code> is thrown.
  450        *
  451        * @param certificate the certificate of the identity whose signature is
  452        * going to be verified.
  453        *
  454        * @exception InvalidKeyException  if the public key in the certificate
  455        * is not encoded properly or does not include required  parameter
  456        * information or cannot be used for digital signature purposes.
  457        * @since 1.3
  458        */
  459       public final void initVerify(Certificate certificate)
  460               throws InvalidKeyException {
  461           // If the certificate is of type X509Certificate,
  462           // we should check whether it has a Key Usage
  463           // extension marked as critical.
  464           if (certificate instanceof java.security.cert.X509Certificate) {
  465               // Check whether the cert has a key usage extension
  466               // marked as a critical extension.
  467               // The OID for KeyUsage extension is 2.5.29.15.
  468               X509Certificate cert = (X509Certificate)certificate;
  469               Set<String> critSet = cert.getCriticalExtensionOIDs();
  470   
  471               if (critSet != null && !critSet.isEmpty()
  472                   && critSet.contains("2.5.29.15")) {
  473                   boolean[] keyUsageInfo = cert.getKeyUsage();
  474                   // keyUsageInfo[0] is for digitalSignature.
  475                   if ((keyUsageInfo != null) && (keyUsageInfo[0] == false))
  476                       throw new InvalidKeyException("Wrong key usage");
  477               }
  478           }
  479   
  480           PublicKey publicKey = certificate.getPublicKey();
  481           engineInitVerify(publicKey);
  482           state = VERIFY;
  483       }
  484   
  485       /**
  486        * Initialize this object for signing. If this method is called
  487        * again with a different argument, it negates the effect
  488        * of this call.
  489        *
  490        * @param privateKey the private key of the identity whose signature
  491        * is going to be generated.
  492        *
  493        * @exception InvalidKeyException if the key is invalid.
  494        */
  495       public final void initSign(PrivateKey privateKey)
  496               throws InvalidKeyException {
  497           engineInitSign(privateKey);
  498           state = SIGN;
  499       }
  500   
  501       /**
  502        * Initialize this object for signing. If this method is called
  503        * again with a different argument, it negates the effect
  504        * of this call.
  505        *
  506        * @param privateKey the private key of the identity whose signature
  507        * is going to be generated.
  508        *
  509        * @param random the source of randomness for this signature.
  510        *
  511        * @exception InvalidKeyException if the key is invalid.
  512        */
  513       public final void initSign(PrivateKey privateKey, SecureRandom random)
  514               throws InvalidKeyException {
  515           engineInitSign(privateKey, random);
  516           state = SIGN;
  517       }
  518   
  519       /**
  520        * Returns the signature bytes of all the data updated.
  521        * The format of the signature depends on the underlying
  522        * signature scheme.
  523        *
  524        * <p>A call to this method resets this signature object to the state
  525        * it was in when previously initialized for signing via a
  526        * call to <code>initSign(PrivateKey)</code>. That is, the object is
  527        * reset and available to generate another signature from the same
  528        * signer, if desired, via new calls to <code>update</code> and
  529        * <code>sign</code>.
  530        *
  531        * @return the signature bytes of the signing operation's result.
  532        *
  533        * @exception SignatureException if this signature object is not
  534        * initialized properly or if this signature algorithm is unable to
  535        * process the input data provided.
  536        */
  537       public final byte[] sign() throws SignatureException {
  538           if (state == SIGN) {
  539               return engineSign();
  540           }
  541           throw new SignatureException("object not initialized for " +
  542                                        "signing");
  543       }
  544   
  545       /**
  546        * Finishes the signature operation and stores the resulting signature
  547        * bytes in the provided buffer <code>outbuf</code>, starting at
  548        * <code>offset</code>.
  549        * The format of the signature depends on the underlying
  550        * signature scheme.
  551        *
  552        * <p>This signature object is reset to its initial state (the state it
  553        * was in after a call to one of the <code>initSign</code> methods) and
  554        * can be reused to generate further signatures with the same private key.
  555        *
  556        * @param outbuf buffer for the signature result.
  557        *
  558        * @param offset offset into <code>outbuf</code> where the signature is
  559        * stored.
  560        *
  561        * @param len number of bytes within <code>outbuf</code> allotted for the
  562        * signature.
  563        *
  564        * @return the number of bytes placed into <code>outbuf</code>.
  565        *
  566        * @exception SignatureException if this signature object is not
  567        * initialized properly, if this signature algorithm is unable to
  568        * process the input data provided, or if <code>len</code> is less
  569        * than the actual signature length.
  570        *
  571        * @since 1.2
  572        */
  573       public final int sign(byte[] outbuf, int offset, int len)
  574           throws SignatureException {
  575           if (outbuf == null) {
  576               throw new IllegalArgumentException("No output buffer given");
  577           }
  578           if (outbuf.length - offset < len) {
  579               throw new IllegalArgumentException
  580                   ("Output buffer too small for specified offset and length");
  581           }
  582           if (state != SIGN) {
  583               throw new SignatureException("object not initialized for " +
  584                                            "signing");
  585           }
  586           return engineSign(outbuf, offset, len);
  587       }
  588   
  589       /**
  590        * Verifies the passed-in signature.
  591        *
  592        * <p>A call to this method resets this signature object to the state
  593        * it was in when previously initialized for verification via a
  594        * call to <code>initVerify(PublicKey)</code>. That is, the object is
  595        * reset and available to verify another signature from the identity
  596        * whose public key was specified in the call to <code>initVerify</code>.
  597        *
  598        * @param signature the signature bytes to be verified.
  599        *
  600        * @return true if the signature was verified, false if not.
  601        *
  602        * @exception SignatureException if this signature object is not
  603        * initialized properly, the passed-in signature is improperly
  604        * encoded or of the wrong type, if this signature algorithm is unable to
  605        * process the input data provided, etc.
  606        */
  607       public final boolean verify(byte[] signature) throws SignatureException {
  608           if (state == VERIFY) {
  609               return engineVerify(signature);
  610           }
  611           throw new SignatureException("object not initialized for " +
  612                                        "verification");
  613       }
  614   
  615       /**
  616        * Verifies the passed-in signature in the specified array
  617        * of bytes, starting at the specified offset.
  618        *
  619        * <p>A call to this method resets this signature object to the state
  620        * it was in when previously initialized for verification via a
  621        * call to <code>initVerify(PublicKey)</code>. That is, the object is
  622        * reset and available to verify another signature from the identity
  623        * whose public key was specified in the call to <code>initVerify</code>.
  624        *
  625        *
  626        * @param signature the signature bytes to be verified.
  627        * @param offset the offset to start from in the array of bytes.
  628        * @param length the number of bytes to use, starting at offset.
  629        *
  630        * @return true if the signature was verified, false if not.
  631        *
  632        * @exception SignatureException if this signature object is not
  633        * initialized properly, the passed-in signature is improperly
  634        * encoded or of the wrong type, if this signature algorithm is unable to
  635        * process the input data provided, etc.
  636        * @exception IllegalArgumentException if the <code>signature</code>
  637        * byte array is null, or the <code>offset</code> or <code>length</code>
  638        * is less than 0, or the sum of the <code>offset</code> and
  639        * <code>length</code> is greater than the length of the
  640        * <code>signature</code> byte array.
  641        * @since 1.4
  642        */
  643       public final boolean verify(byte[] signature, int offset, int length)
  644           throws SignatureException {
  645           if (state == VERIFY) {
  646               if ((signature == null) || (offset < 0) || (length < 0) ||
  647                   (offset + length > signature.length)) {
  648                   throw new IllegalArgumentException("Bad arguments");
  649               }
  650   
  651               return engineVerify(signature, offset, length);
  652           }
  653           throw new SignatureException("object not initialized for " +
  654                                        "verification");
  655       }
  656   
  657       /**
  658        * Updates the data to be signed or verified by a byte.
  659        *
  660        * @param b the byte to use for the update.
  661        *
  662        * @exception SignatureException if this signature object is not
  663        * initialized properly.
  664        */
  665       public final void update(byte b) throws SignatureException {
  666           if (state == VERIFY || state == SIGN) {
  667               engineUpdate(b);
  668           } else {
  669               throw new SignatureException("object not initialized for "
  670                                            + "signature or verification");
  671           }
  672       }
  673   
  674       /**
  675        * Updates the data to be signed or verified, using the specified
  676        * array of bytes.
  677        *
  678        * @param data the byte array to use for the update.
  679        *
  680        * @exception SignatureException if this signature object is not
  681        * initialized properly.
  682        */
  683       public final void update(byte[] data) throws SignatureException {
  684           update(data, 0, data.length);
  685       }
  686   
  687       /**
  688        * Updates the data to be signed or verified, using the specified
  689        * array of bytes, starting at the specified offset.
  690        *
  691        * @param data the array of bytes.
  692        * @param off the offset to start from in the array of bytes.
  693        * @param len the number of bytes to use, starting at offset.
  694        *
  695        * @exception SignatureException if this signature object is not
  696        * initialized properly.
  697        */
  698       public final void update(byte[] data, int off, int len)
  699               throws SignatureException {
  700           if (state == SIGN || state == VERIFY) {
  701               engineUpdate(data, off, len);
  702           } else {
  703               throw new SignatureException("object not initialized for "
  704                                            + "signature or verification");
  705           }
  706       }
  707   
  708       /**
  709        * Updates the data to be signed or verified using the specified
  710        * ByteBuffer. Processes the <code>data.remaining()</code> bytes
  711        * starting at at <code>data.position()</code>.
  712        * Upon return, the buffer's position will be equal to its limit;
  713        * its limit will not have changed.
  714        *
  715        * @param data the ByteBuffer
  716        *
  717        * @exception SignatureException if this signature object is not
  718        * initialized properly.
  719        * @since 1.5
  720        */
  721       public final void update(ByteBuffer data) throws SignatureException {
  722           if ((state != SIGN) && (state != VERIFY)) {
  723               throw new SignatureException("object not initialized for "
  724                                            + "signature or verification");
  725           }
  726           if (data == null) {
  727               throw new NullPointerException();
  728           }
  729           engineUpdate(data);
  730       }
  731   
  732       /**
  733        * Returns the name of the algorithm for this signature object.
  734        *
  735        * @return the name of the algorithm for this signature object.
  736        */
  737       public final String getAlgorithm() {
  738           return this.algorithm;
  739       }
  740   
  741       /**
  742        * Returns a string representation of this signature object,
  743        * providing information that includes the state of the object
  744        * and the name of the algorithm used.
  745        *
  746        * @return a string representation of this signature object.
  747        */
  748       public String toString() {
  749           String initState = "";
  750           switch (state) {
  751           case UNINITIALIZED:
  752               initState = "<not initialized>";
  753               break;
  754           case VERIFY:
  755               initState = "<initialized for verifying>";
  756               break;
  757           case SIGN:
  758               initState = "<initialized for signing>";
  759               break;
  760           }
  761           return "Signature object: " + getAlgorithm() + initState;
  762       }
  763   
  764       /**
  765        * Sets the specified algorithm parameter to the specified value.
  766        * This method supplies a general-purpose mechanism through
  767        * which it is possible to set the various parameters of this object.
  768        * A parameter may be any settable parameter for the algorithm, such as
  769        * a parameter size, or a source of random bits for signature generation
  770        * (if appropriate), or an indication of whether or not to perform
  771        * a specific but optional computation. A uniform algorithm-specific
  772        * naming scheme for each parameter is desirable but left unspecified
  773        * at this time.
  774        *
  775        * @param param the string identifier of the parameter.
  776        * @param value the parameter value.
  777        *
  778        * @exception InvalidParameterException if <code>param</code> is an
  779        * invalid parameter for this signature algorithm engine,
  780        * the parameter is already set
  781        * and cannot be set again, a security exception occurs, and so on.
  782        *
  783        * @see #getParameter
  784        *
  785        * @deprecated Use
  786        * {@link #setParameter(java.security.spec.AlgorithmParameterSpec)
  787        * setParameter}.
  788        */
  789       @Deprecated
  790       public final void setParameter(String param, Object value)
  791               throws InvalidParameterException {
  792           engineSetParameter(param, value);
  793       }
  794   
  795       /**
  796        * Initializes this signature engine with the specified parameter set.
  797        *
  798        * @param params the parameters
  799        *
  800        * @exception InvalidAlgorithmParameterException if the given parameters
  801        * are inappropriate for this signature engine
  802        *
  803        * @see #getParameters
  804        */
  805       public final void setParameter(AlgorithmParameterSpec params)
  806               throws InvalidAlgorithmParameterException {
  807           engineSetParameter(params);
  808       }
  809   
  810       /**
  811        * Returns the parameters used with this signature object.
  812        *
  813        * <p>The returned parameters may be the same that were used to initialize
  814        * this signature, or may contain a combination of default and randomly
  815        * generated parameter values used by the underlying signature
  816        * implementation if this signature requires algorithm parameters but
  817        * was not initialized with any.
  818        *
  819        * @return the parameters used with this signature, or null if this
  820        * signature does not use any parameters.
  821        *
  822        * @see #setParameter(AlgorithmParameterSpec)
  823        * @since 1.4
  824        */
  825       public final AlgorithmParameters getParameters() {
  826           return engineGetParameters();
  827       }
  828   
  829       /**
  830        * Gets the value of the specified algorithm parameter. This method
  831        * supplies a general-purpose mechanism through which it is possible to
  832        * get the various parameters of this object. A parameter may be any
  833        * settable parameter for the algorithm, such as a parameter size, or
  834        * a source of random bits for signature generation (if appropriate),
  835        * or an indication of whether or not to perform a specific but optional
  836        * computation. A uniform algorithm-specific naming scheme for each
  837        * parameter is desirable but left unspecified at this time.
  838        *
  839        * @param param the string name of the parameter.
  840        *
  841        * @return the object that represents the parameter value, or null if
  842        * there is none.
  843        *
  844        * @exception InvalidParameterException if <code>param</code> is an invalid
  845        * parameter for this engine, or another exception occurs while
  846        * trying to get this parameter.
  847        *
  848        * @see #setParameter(String, Object)
  849        *
  850        * @deprecated
  851        */
  852       @Deprecated
  853       public final Object getParameter(String param)
  854               throws InvalidParameterException {
  855           return engineGetParameter(param);
  856       }
  857   
  858       /**
  859        * Returns a clone if the implementation is cloneable.
  860        *
  861        * @return a clone if the implementation is cloneable.
  862        *
  863        * @exception CloneNotSupportedException if this is called
  864        * on an implementation that does not support <code>Cloneable</code>.
  865        */
  866       public Object clone() throws CloneNotSupportedException {
  867           if (this instanceof Cloneable) {
  868               return super.clone();
  869           } else {
  870               throw new CloneNotSupportedException();
  871           }
  872       }
  873   
  874       /*
  875        * The following class allows providers to extend from SignatureSpi
  876        * rather than from Signature. It represents a Signature with an
  877        * encapsulated, provider-supplied SPI object (of type SignatureSpi).
  878        * If the provider implementation is an instance of SignatureSpi, the
  879        * getInstance() methods above return an instance of this class, with
  880        * the SPI object encapsulated.
  881        *
  882        * Note: All SPI methods from the original Signature class have been
  883        * moved up the hierarchy into a new class (SignatureSpi), which has
  884        * been interposed in the hierarchy between the API (Signature)
  885        * and its original parent (Object).
  886        */
  887   
  888       private static class Delegate extends Signature {
  889   
  890           // The provider implementation (delegate)
  891           // filled in once the provider is selected
  892           private SignatureSpi sigSpi;
  893   
  894           // lock for mutex during provider selection
  895           private final Object lock;
  896   
  897           // next service to try in provider selection
  898           // null once provider is selected
  899           private Service firstService;
  900   
  901           // remaining services to try in provider selection
  902           // null once provider is selected
  903           private Iterator<Service> serviceIterator;
  904   
  905           // constructor
  906           Delegate(SignatureSpi sigSpi, String algorithm) {
  907               super(algorithm);
  908               this.sigSpi = sigSpi;
  909               this.lock = null; // no lock needed
  910           }
  911   
  912           // used with delayed provider selection
  913           Delegate(Service service,
  914                           Iterator<Service> iterator, String algorithm) {
  915               super(algorithm);
  916               this.firstService = service;
  917               this.serviceIterator = iterator;
  918               this.lock = new Object();
  919           }
  920   
  921           /**
  922            * Returns a clone if the delegate is cloneable.
  923            *
  924            * @return a clone if the delegate is cloneable.
  925            *
  926            * @exception CloneNotSupportedException if this is called on a
  927            * delegate that does not support <code>Cloneable</code>.
  928            */
  929           public Object clone() throws CloneNotSupportedException {
  930               chooseFirstProvider();
  931               if (sigSpi instanceof Cloneable) {
  932                   SignatureSpi sigSpiClone = (SignatureSpi)sigSpi.clone();
  933                   // Because 'algorithm' and 'provider' are private
  934                   // members of our supertype, we must perform a cast to
  935                   // access them.
  936                   Signature that =
  937                       new Delegate(sigSpiClone, ((Signature)this).algorithm);
  938                   that.provider = ((Signature)this).provider;
  939                   return that;
  940               } else {
  941                   throw new CloneNotSupportedException();
  942               }
  943           }
  944   
  945           private static SignatureSpi newInstance(Service s)
  946                   throws NoSuchAlgorithmException {
  947               if (s.getType().equals("Cipher")) {
  948                   // must be NONEwithRSA
  949                   try {
  950                       Cipher c = Cipher.getInstance(RSA_CIPHER, s.getProvider());
  951                       return new CipherAdapter(c);
  952                   } catch (NoSuchPaddingException e) {
  953                       throw new NoSuchAlgorithmException(e);
  954                   }
  955               } else {
  956                   Object o = s.newInstance(null);
  957                   if (o instanceof SignatureSpi == false) {
  958                       throw new NoSuchAlgorithmException
  959                           ("Not a SignatureSpi: " + o.getClass().getName());
  960                   }
  961                   return (SignatureSpi)o;
  962               }
  963           }
  964   
  965           // max number of debug warnings to print from chooseFirstProvider()
  966           private static int warnCount = 10;
  967   
  968           /**
  969            * Choose the Spi from the first provider available. Used if
  970            * delayed provider selection is not possible because initSign()/
  971            * initVerify() is not the first method called.
  972            */
  973           void chooseFirstProvider() {
  974               if (sigSpi != null) {
  975                   return;
  976               }
  977               synchronized (lock) {
  978                   if (sigSpi != null) {
  979                       return;
  980                   }
  981                   if (debug != null) {
  982                       int w = --warnCount;
  983                       if (w >= 0) {
  984                           debug.println("Signature.init() not first method "
  985                               + "called, disabling delayed provider selection");
  986                           if (w == 0) {
  987                               debug.println("Further warnings of this type will "
  988                                   + "be suppressed");
  989                           }
  990                           new Exception("Call trace").printStackTrace();
  991                       }
  992                   }
  993                   Exception lastException = null;
  994                   while ((firstService != null) || serviceIterator.hasNext()) {
  995                       Service s;
  996                       if (firstService != null) {
  997                           s = firstService;
  998                           firstService = null;
  999                       } else {
 1000                           s = serviceIterator.next();
 1001                       }
 1002                       if (isSpi(s) == false) {
 1003                           continue;
 1004                       }
 1005                       try {
 1006                           sigSpi = newInstance(s);
 1007                           provider = s.getProvider();
 1008                           // not needed any more
 1009                           firstService = null;
 1010                           serviceIterator = null;
 1011                           return;
 1012                       } catch (NoSuchAlgorithmException e) {
 1013                           lastException = e;
 1014                       }
 1015                   }
 1016                   ProviderException e = new ProviderException
 1017                           ("Could not construct SignatureSpi instance");
 1018                   if (lastException != null) {
 1019                       e.initCause(lastException);
 1020                   }
 1021                   throw e;
 1022               }
 1023           }
 1024   
 1025           private void chooseProvider(int type, Key key, SecureRandom random)
 1026                   throws InvalidKeyException {
 1027               synchronized (lock) {
 1028                   if (sigSpi != null) {
 1029                       init(sigSpi, type, key, random);
 1030                       return;
 1031                   }
 1032                   Exception lastException = null;
 1033                   while ((firstService != null) || serviceIterator.hasNext()) {
 1034                       Service s;
 1035                       if (firstService != null) {
 1036                           s = firstService;
 1037                           firstService = null;
 1038                       } else {
 1039                           s = serviceIterator.next();
 1040                       }
 1041                       // if provider says it does not support this key, ignore it
 1042                       if (s.supportsParameter(key) == false) {
 1043                           continue;
 1044                       }
 1045                       // if instance is not a SignatureSpi, ignore it
 1046                       if (isSpi(s) == false) {
 1047                           continue;
 1048                       }
 1049                       try {
 1050                           SignatureSpi spi = newInstance(s);
 1051                           init(spi, type, key, random);
 1052                           provider = s.getProvider();
 1053                           sigSpi = spi;
 1054                           firstService = null;
 1055                           serviceIterator = null;
 1056                           return;
 1057                       } catch (Exception e) {
 1058                           // NoSuchAlgorithmException from newInstance()
 1059                           // InvalidKeyException from init()
 1060                           // RuntimeException (ProviderException) from init()
 1061                           if (lastException == null) {
 1062                               lastException = e;
 1063                           }
 1064                       }
 1065                   }
 1066                   // no working provider found, fail
 1067                   if (lastException instanceof InvalidKeyException) {
 1068                       throw (InvalidKeyException)lastException;
 1069                   }
 1070                   if (lastException instanceof RuntimeException) {
 1071                       throw (RuntimeException)lastException;
 1072                   }
 1073                   String k = (key != null) ? key.getClass().getName() : "(null)";
 1074                   throw new InvalidKeyException
 1075                       ("No installed provider supports this key: "
 1076                       + k, lastException);
 1077               }
 1078           }
 1079   
 1080           private final static int I_PUB     = 1;
 1081           private final static int I_PRIV    = 2;
 1082           private final static int I_PRIV_SR = 3;
 1083   
 1084           private void init(SignatureSpi spi, int type, Key  key,
 1085                   SecureRandom random) throws InvalidKeyException {
 1086               switch (type) {
 1087               case I_PUB:
 1088                   spi.engineInitVerify((PublicKey)key);
 1089                   break;
 1090               case I_PRIV:
 1091                   spi.engineInitSign((PrivateKey)key);
 1092                   break;
 1093               case I_PRIV_SR:
 1094                   spi.engineInitSign((PrivateKey)key, random);
 1095                   break;
 1096               default:
 1097                   throw new AssertionError("Internal error: " + type);
 1098               }
 1099           }
 1100   
 1101           protected void engineInitVerify(PublicKey publicKey)
 1102                   throws InvalidKeyException {
 1103               if (sigSpi != null) {
 1104                   sigSpi.engineInitVerify(publicKey);
 1105               } else {
 1106                   chooseProvider(I_PUB, publicKey, null);
 1107               }
 1108           }
 1109   
 1110           protected void engineInitSign(PrivateKey privateKey)
 1111                   throws InvalidKeyException {
 1112               if (sigSpi != null) {
 1113                   sigSpi.engineInitSign(privateKey);
 1114               } else {
 1115                   chooseProvider(I_PRIV, privateKey, null);
 1116               }
 1117           }
 1118   
 1119           protected void engineInitSign(PrivateKey privateKey, SecureRandom sr)
 1120                   throws InvalidKeyException {
 1121               if (sigSpi != null) {
 1122                   sigSpi.engineInitSign(privateKey, sr);
 1123               } else {
 1124                   chooseProvider(I_PRIV_SR, privateKey, sr);
 1125               }
 1126           }
 1127   
 1128           protected void engineUpdate(byte b) throws SignatureException {
 1129               chooseFirstProvider();
 1130               sigSpi.engineUpdate(b);
 1131           }
 1132   
 1133           protected void engineUpdate(byte[] b, int off, int len)
 1134                   throws SignatureException {
 1135               chooseFirstProvider();
 1136               sigSpi.engineUpdate(b, off, len);
 1137           }
 1138   
 1139           protected void engineUpdate(ByteBuffer data) {
 1140               chooseFirstProvider();
 1141               sigSpi.engineUpdate(data);
 1142           }
 1143   
 1144           protected byte[] engineSign() throws SignatureException {
 1145               chooseFirstProvider();
 1146               return sigSpi.engineSign();
 1147           }
 1148   
 1149           protected int engineSign(byte[] outbuf, int offset, int len)
 1150                   throws SignatureException {
 1151               chooseFirstProvider();
 1152               return sigSpi.engineSign(outbuf, offset, len);
 1153           }
 1154   
 1155           protected boolean engineVerify(byte[] sigBytes)
 1156                   throws SignatureException {
 1157               chooseFirstProvider();
 1158               return sigSpi.engineVerify(sigBytes);
 1159           }
 1160   
 1161           protected boolean engineVerify(byte[] sigBytes, int offset, int length)
 1162                   throws SignatureException {
 1163               chooseFirstProvider();
 1164               return sigSpi.engineVerify(sigBytes, offset, length);
 1165           }
 1166   
 1167           protected void engineSetParameter(String param, Object value)
 1168                   throws InvalidParameterException {
 1169               chooseFirstProvider();
 1170               sigSpi.engineSetParameter(param, value);
 1171           }
 1172   
 1173           protected void engineSetParameter(AlgorithmParameterSpec params)
 1174                   throws InvalidAlgorithmParameterException {
 1175               chooseFirstProvider();
 1176               sigSpi.engineSetParameter(params);
 1177           }
 1178   
 1179           protected Object engineGetParameter(String param)
 1180                   throws InvalidParameterException {
 1181               chooseFirstProvider();
 1182               return sigSpi.engineGetParameter(param);
 1183           }
 1184   
 1185           protected AlgorithmParameters engineGetParameters() {
 1186               chooseFirstProvider();
 1187               return sigSpi.engineGetParameters();
 1188           }
 1189       }
 1190   
 1191       // adapter for RSA/ECB/PKCS1Padding ciphers
 1192       private static class CipherAdapter extends SignatureSpi {
 1193   
 1194           private final Cipher cipher;
 1195   
 1196           private ByteArrayOutputStream data;
 1197   
 1198           CipherAdapter(Cipher cipher) {
 1199               this.cipher = cipher;
 1200           }
 1201   
 1202           protected void engineInitVerify(PublicKey publicKey)
 1203                   throws InvalidKeyException {
 1204               cipher.init(Cipher.DECRYPT_MODE, publicKey);
 1205               if (data == null) {
 1206                   data = new ByteArrayOutputStream(128);
 1207               } else {
 1208                   data.reset();
 1209               }
 1210           }
 1211   
 1212           protected void engineInitSign(PrivateKey privateKey)
 1213                   throws InvalidKeyException {
 1214               cipher.init(Cipher.ENCRYPT_MODE, privateKey);
 1215               data = null;
 1216           }
 1217   
 1218           protected void engineInitSign(PrivateKey privateKey,
 1219                   SecureRandom random) throws InvalidKeyException {
 1220               cipher.init(Cipher.ENCRYPT_MODE, privateKey, random);
 1221               data = null;
 1222           }
 1223   
 1224           protected void engineUpdate(byte b) throws SignatureException {
 1225               engineUpdate(new byte[] {b}, 0, 1);
 1226           }
 1227   
 1228           protected void engineUpdate(byte[] b, int off, int len)
 1229                   throws SignatureException {
 1230               if (data != null) {
 1231                   data.write(b, off, len);
 1232                   return;
 1233               }
 1234               byte[] out = cipher.update(b, off, len);
 1235               if ((out != null) && (out.length != 0)) {
 1236                   throw new SignatureException
 1237                       ("Cipher unexpectedly returned data");
 1238               }
 1239           }
 1240   
 1241           protected byte[] engineSign() throws SignatureException {
 1242               try {
 1243                   return cipher.doFinal();
 1244               } catch (IllegalBlockSizeException e) {
 1245                   throw new SignatureException("doFinal() failed", e);
 1246               } catch (BadPaddingException e) {
 1247                   throw new SignatureException("doFinal() failed", e);
 1248               }
 1249           }
 1250   
 1251           protected boolean engineVerify(byte[] sigBytes)
 1252                   throws SignatureException {
 1253               try {
 1254                   byte[] out = cipher.doFinal(sigBytes);
 1255                   byte[] dataBytes = data.toByteArray();
 1256                   data.reset();
 1257                   return Arrays.equals(out, dataBytes);
 1258               } catch (BadPaddingException e) {
 1259                   // e.g. wrong public key used
 1260                   // return false rather than throwing exception
 1261                   return false;
 1262               } catch (IllegalBlockSizeException e) {
 1263                   throw new SignatureException("doFinal() failed", e);
 1264               }
 1265           }
 1266   
 1267           protected void engineSetParameter(String param, Object value)
 1268                   throws InvalidParameterException {
 1269               throw new InvalidParameterException("Parameters not supported");
 1270           }
 1271   
 1272           protected Object engineGetParameter(String param)
 1273                   throws InvalidParameterException {
 1274               throw new InvalidParameterException("Parameters not supported");
 1275           }
 1276   
 1277       }
 1278   
 1279   }

Save This Page
Home » openjdk-7 » java » security » [javadoc | source]