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

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