/* * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.security; import java.security.spec.AlgorithmParameterSpec;import java.util.*;import java.util.concurrent.ConcurrentHashMap;import java.io.*;import java.security.cert.Certificate;import java.security.cert.X509Certificate; import java.nio.ByteBuffer; import java.security.Provider.Service; import javax.crypto.Cipher;import javax.crypto.CipherSpi;import javax.crypto.IllegalBlockSizeException;import javax.crypto.BadPaddingException;import javax.crypto.NoSuchPaddingException; import sun.security.util.Debug;import sun.security.jca.*;import sun.security.jca.GetInstance.Instance; /** * The Signature class is used to provide applications the functionality * of a digital signature algorithm. Digital signatures are used for * authentication and integrity assurance of digital data. * * <p> The signature algorithm can be, among others, the NIST standard * DSA, using DSA and SHA-1. The DSA algorithm using the * SHA-1 message digest algorithm can be specified as <tt>SHA1withDSA</tt>. * In the case of RSA, there are multiple choices for the message digest * algorithm, so the signing algorithm could be specified as, for example, * <tt>MD2withRSA</tt>, <tt>MD5withRSA</tt>, or <tt>SHA1withRSA</tt>. * The algorithm name must be specified, as there is no default. * * <p> A Signature object can be used to generate and verify digital * signatures. * * <p> There are three phases to the use of a Signature object for * either signing data or verifying a signature:<ol> * * <li>Initialization, with either * * <ul> * * <li>a public key, which initializes the signature for * verification (see {@link #initVerify(PublicKey) initVerify}), or * * <li>a private key (and optionally a Secure Random Number Generator), * which initializes the signature for signing * (see {@link #initSign(PrivateKey)} * and {@link #initSign(PrivateKey, SecureRandom)}). * * </ul><p> * * <li>Updating<p> * * <p>Depending on the type of initialization, this will update the * bytes to be signed or verified. See the * {@link #update(byte) update} methods.<p> * * <li>Signing or Verifying a signature on all updated bytes. See the * {@link #sign() sign} methods and the {@link #verify(byte[]) verify} * method. * * </ol> * * <p>Note that this class is abstract and extends from * <code>SignatureSpi</code> for historical reasons. * Application developers should only take notice of the methods defined in * this <code>Signature</code> class; all the methods in * the superclass are intended for cryptographic service providers who wish to * supply their own implementations of digital signature algorithms. * * <p> Every implementation of the Java platform is required to support the * following standard <code>Signature</code> algorithms: * <ul> * <li><tt>SHA1withDSA</tt></li> * <li><tt>SHA1withRSA</tt></li> * <li><tt>SHA256withRSA</tt></li> * </ul> * These algorithms are described in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Signature section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any * other algorithms are supported. * * @author Benjamin Renaud * */ public abstract class Signature extends SignatureSpi { private static final Debug debug = Debug.getInstance("jca", "Signature"); /* * The algorithm for this signature object. * This value is used to map an OID to the particular algorithm. * The mapping is done in AlgorithmObject.algOID(String algorithm) */ private String algorithm; // The provider Provider provider; /** * Possible {@link #state} value, signifying that * this signature object has not yet been initialized. */ protected final static int UNINITIALIZED = 0; /** * Possible {@link #state} value, signifying that * this signature object has been initialized for signing. */ protected final static int SIGN = 2; /** * Possible {@link #state} value, signifying that * this signature object has been initialized for verification. */ protected final static int VERIFY = 3; /** * Current state of this signature object. */ protected int state = UNINITIALIZED; /** * Creates a Signature object for the specified algorithm. * * @param algorithm the standard string name of the algorithm. * See the Signature section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. */ protected Signature(String algorithm) { this.algorithm = algorithm; } // name of the special signature alg private final static String RSA_SIGNATURE = "NONEwithRSA"; // name of the equivalent cipher alg private final static String RSA_CIPHER = "RSA/ECB/PKCS1Padding"; // all the services we need to lookup for compatibility with Cipher private final static List<ServiceId> rsaIds = Arrays.asList( new ServiceId[] { new ServiceId("Signature", "NONEwithRSA"), new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"), new ServiceId("Cipher", "RSA/ECB"), new ServiceId("Cipher", "RSA//PKCS1Padding"), new ServiceId("Cipher", "RSA"), } ); /** * Returns a Signature object that implements the specified signature * algorithm. * * <p> This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new Signature object encapsulating the * SignatureSpi implementation from the first * Provider that supports the specified algorithm is returned. * * <p> Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the algorithm requested. * See the Signature section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * * @return the new Signature object. * * @exception NoSuchAlgorithmException if no Provider supports a * Signature implementation for the * specified algorithm. * * @see Provider */ public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException { List<Service> list; if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { list = GetInstance.getServices(rsaIds); } else { list = GetInstance.getServices("Signature", algorithm); } Iterator<Service> t = list.iterator(); if (t.hasNext() == false) { throw new NoSuchAlgorithmException (algorithm + " Signature not available"); } // try services until we find an Spi or a working Signature subclass NoSuchAlgorithmException failure; do { Service s = t.next(); if (isSpi(s)) { return new Delegate(s, t, algorithm); } else { // must be a subclass of Signature, disable dynamic selection try { Instance instance = GetInstance.getInstance(s, SignatureSpi.class); return getInstance(instance, algorithm); } catch (NoSuchAlgorithmException e) { failure = e; } } } while (t.hasNext()); throw failure; } private static Signature getInstance(Instance instance, String algorithm) { Signature sig; if (instance.impl instanceof Signature) { sig = (Signature)instance.impl; } else { SignatureSpi spi = (SignatureSpi)instance.impl; sig = new Delegate(spi, algorithm); } sig.provider = instance.provider; return sig; } private final static Map<String,Boolean> signatureInfo; static { signatureInfo = new ConcurrentHashMap<String,Boolean>(); Boolean TRUE = Boolean.TRUE; // pre-initialize with values for our SignatureSpi implementations signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE); signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE); signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE); signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE); } private static boolean isSpi(Service s) { if (s.getType().equals("Cipher")) { // must be a CipherSpi, which we can wrap with the CipherAdapter return true; } String className = s.getClassName(); Boolean result = signatureInfo.get(className); if (result == null) { try { Object instance = s.newInstance(null); // Signature extends SignatureSpi // so it is a "real" Spi if it is an // instance of SignatureSpi but not Signature boolean r = (instance instanceof SignatureSpi) && (instance instanceof Signature == false); if ((debug != null) && (r == false)) { debug.println("Not a SignatureSpi " + className); debug.println("Delayed provider selection may not be " + "available for algorithm " + s.getAlgorithm()); } result = Boolean.valueOf(r); signatureInfo.put(className, result); } catch (Exception e) { // something is wrong, assume not an SPI return false; } } return result.booleanValue(); } /** * Returns a Signature object that implements the specified signature * algorithm. * * <p> A new Signature object encapsulating the * SignatureSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * * <p> Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. * See the Signature section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new Signature object. * * @exception NoSuchAlgorithmException if a SignatureSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static Signature getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { // exception compatibility with existing code if ((provider == null) || (provider.length() == 0)) { throw new IllegalArgumentException("missing provider"); } Provider p = Security.getProvider(provider); if (p == null) { throw new NoSuchProviderException ("no such provider: " + provider); } return getInstanceRSA(p); } Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); } /** * Returns a Signature object that implements the specified * signature algorithm. * * <p> A new Signature object encapsulating the * SignatureSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the name of the algorithm requested. * See the Signature section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * * @param provider the provider. * * @return the new Signature object. * * @exception NoSuchAlgorithmException if a SignatureSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the provider is null. * * @see Provider * * @since 1.4 */ public static Signature getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { // exception compatibility with existing code if (provider == null) { throw new IllegalArgumentException("missing provider"); } return getInstanceRSA(provider); } Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); } // return an implementation for NONEwithRSA, which is a special case // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper private static Signature getInstanceRSA(Provider p) throws NoSuchAlgorithmException { // try Signature first Service s = p.getService("Signature", RSA_SIGNATURE); if (s != null) { Instance instance = GetInstance.getInstance(s, SignatureSpi.class); return getInstance(instance, RSA_SIGNATURE); } // check Cipher try { Cipher c = Cipher.getInstance(RSA_CIPHER, p); return new Delegate(new CipherAdapter(c), RSA_SIGNATURE); } catch (GeneralSecurityException e) { // throw Signature style exception message to avoid confusion, // but append Cipher exception as cause throw new NoSuchAlgorithmException("no such algorithm: " + RSA_SIGNATURE + " for provider " + p.getName(), e); } } /** * Returns the provider of this signature object. * * @return the provider of this signature object */ public final Provider getProvider() { chooseFirstProvider(); return this.provider; } void chooseFirstProvider() { // empty, overridden in Delegate } /** * Initializes this object for verification. If this method is called * again with a different argument, it negates the effect * of this call. * * @param publicKey the public key of the identity whose signature is * going to be verified. * * @exception InvalidKeyException if the key is invalid. */ public final void initVerify(PublicKey publicKey) throws InvalidKeyException { engineInitVerify(publicKey); state = VERIFY; } /** * Initializes this object for verification, using the public key from * the given certificate. * <p>If the certificate is of type X.509 and has a <i>key usage</i> * extension field marked as critical, and the value of the <i>key usage</i> * extension field implies that the public key in * the certificate and its corresponding private key are not * supposed to be used for digital signatures, an * <code>InvalidKeyException</code> is thrown. * * @param certificate the certificate of the identity whose signature is * going to be verified. * * @exception InvalidKeyException if the public key in the certificate * is not encoded properly or does not include required parameter * information or cannot be used for digital signature purposes. * @since 1.3 */ public final void initVerify(Certificate certificate) throws InvalidKeyException { // If the certificate is of type X509Certificate, // we should check whether it has a Key Usage // extension marked as critical. if (certificate instanceof java.security.cert.X509Certificate) { // Check whether the cert has a key usage extension // marked as a critical extension. // The OID for KeyUsage extension is 2.5.29.15. X509Certificate cert = (X509Certificate)certificate; Set<String> critSet = cert.getCriticalExtensionOIDs(); if (critSet != null && !critSet.isEmpty() && critSet.contains("2.5.29.15")) { boolean[] keyUsageInfo = cert.getKeyUsage(); // keyUsageInfo[0] is for digitalSignature. if ((keyUsageInfo != null) && (keyUsageInfo[0] == false)) throw new InvalidKeyException("Wrong key usage"); } } PublicKey publicKey = certificate.getPublicKey(); engineInitVerify(publicKey); state = VERIFY; } /** * Initialize this object for signing. If this method is calledLines 1–500 of 1293. Load more
/* * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.security; import java.security.spec.AlgorithmParameterSpec; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.io.*; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.nio.ByteBuffer; import java.security.Provider.Service; import javax.crypto.Cipher; import javax.crypto.CipherSpi; import javax.crypto.IllegalBlockSizeException; import javax.crypto.BadPaddingException; import javax.crypto.NoSuchPaddingException; import sun.security.util.Debug; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** * The Signature class is used to provide applications the functionality * of a digital signature algorithm. Digital signatures are used for * authentication and integrity assurance of digital data. * * <p> The signature algorithm can be, among others, the NIST standard * DSA, using DSA and SHA-1. The DSA algorithm using the * SHA-1 message digest algorithm can be specified as <tt>SHA1withDSA</tt>. * In the case of RSA, there are multiple choices for the message digest * algorithm, so the signing algorithm could be specified as, for example, * <tt>MD2withRSA</tt>, <tt>MD5withRSA</tt>, or <tt>SHA1withRSA</tt>. * The algorithm name must be specified, as there is no default. * * <p> A Signature object can be used to generate and verify digital * signatures. * * <p> There are three phases to the use of a Signature object for * either signing data or verifying a signature:<ol> * * <li>Initialization, with either * * <ul> * * <li>a public key, which initializes the signature for * verification (see {@link #initVerify(PublicKey) initVerify}), or * * <li>a private key (and optionally a Secure Random Number Generator), * which initializes the signature for signing * (see {@link #initSign(PrivateKey)} * and {@link #initSign(PrivateKey, SecureRandom)}). * * </ul><p> * * <li>Updating<p> * * <p>Depending on the type of initialization, this will update the * bytes to be signed or verified. See the * {@link #update(byte) update} methods.<p> * * <li>Signing or Verifying a signature on all updated bytes. See the * {@link #sign() sign} methods and the {@link #verify(byte[]) verify} * method. * * </ol> * * <p>Note that this class is abstract and extends from * <code>SignatureSpi</code> for historical reasons. * Application developers should only take notice of the methods defined in * this <code>Signature</code> class; all the methods in * the superclass are intended for cryptographic service providers who wish to * supply their own implementations of digital signature algorithms. * * <p> Every implementation of the Java platform is required to support the * following standard <code>Signature</code> algorithms: * <ul> * <li><tt>SHA1withDSA</tt></li> * <li><tt>SHA1withRSA</tt></li> * <li><tt>SHA256withRSA</tt></li> * </ul> * These algorithms are described in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Signature section</a> of the * Java Cryptography Architecture Standard Algorithm Name Documentation. * Consult the release documentation for your implementation to see if any * other algorithms are supported. * * @author Benjamin Renaud * */ public abstract class Signature extends SignatureSpi { private static final Debug debug = Debug.getInstance("jca", "Signature"); /* * The algorithm for this signature object. * This value is used to map an OID to the particular algorithm. * The mapping is done in AlgorithmObject.algOID(String algorithm) */ private String algorithm; // The provider Provider provider; /** * Possible {@link #state} value, signifying that * this signature object has not yet been initialized. */ protected final static int UNINITIALIZED = 0; /** * Possible {@link #state} value, signifying that * this signature object has been initialized for signing. */ protected final static int SIGN = 2; /** * Possible {@link #state} value, signifying that * this signature object has been initialized for verification. */ protected final static int VERIFY = 3; /** * Current state of this signature object. */ protected int state = UNINITIALIZED; /** * Creates a Signature object for the specified algorithm. * * @param algorithm the standard string name of the algorithm. * See the Signature section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. */ protected Signature(String algorithm) { this.algorithm = algorithm; } // name of the special signature alg private final static String RSA_SIGNATURE = "NONEwithRSA"; // name of the equivalent cipher alg private final static String RSA_CIPHER = "RSA/ECB/PKCS1Padding"; // all the services we need to lookup for compatibility with Cipher private final static List<ServiceId> rsaIds = Arrays.asList( new ServiceId[] { new ServiceId("Signature", "NONEwithRSA"), new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"), new ServiceId("Cipher", "RSA/ECB"), new ServiceId("Cipher", "RSA//PKCS1Padding"), new ServiceId("Cipher", "RSA"), } ); /** * Returns a Signature object that implements the specified signature * algorithm. * * <p> This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new Signature object encapsulating the * SignatureSpi implementation from the first * Provider that supports the specified algorithm is returned. * * <p> Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the algorithm requested. * See the Signature section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * * @return the new Signature object. * * @exception NoSuchAlgorithmException if no Provider supports a * Signature implementation for the * specified algorithm. * * @see Provider */ public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException { List<Service> list; if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { list = GetInstance.getServices(rsaIds); } else { list = GetInstance.getServices("Signature", algorithm); } Iterator<Service> t = list.iterator(); if (t.hasNext() == false) { throw new NoSuchAlgorithmException (algorithm + " Signature not available"); } // try services until we find an Spi or a working Signature subclass NoSuchAlgorithmException failure; do { Service s = t.next(); if (isSpi(s)) { return new Delegate(s, t, algorithm); } else { // must be a subclass of Signature, disable dynamic selection try { Instance instance = GetInstance.getInstance(s, SignatureSpi.class); return getInstance(instance, algorithm); } catch (NoSuchAlgorithmException e) { failure = e; } } } while (t.hasNext()); throw failure; } private static Signature getInstance(Instance instance, String algorithm) { Signature sig; if (instance.impl instanceof Signature) { sig = (Signature)instance.impl; } else { SignatureSpi spi = (SignatureSpi)instance.impl; sig = new Delegate(spi, algorithm); } sig.provider = instance.provider; return sig; } private final static Map<String,Boolean> signatureInfo; static { signatureInfo = new ConcurrentHashMap<String,Boolean>(); Boolean TRUE = Boolean.TRUE; // pre-initialize with values for our SignatureSpi implementations signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE); signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE); signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE); signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE); signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE); } private static boolean isSpi(Service s) { if (s.getType().equals("Cipher")) { // must be a CipherSpi, which we can wrap with the CipherAdapter return true; } String className = s.getClassName(); Boolean result = signatureInfo.get(className); if (result == null) { try { Object instance = s.newInstance(null); // Signature extends SignatureSpi // so it is a "real" Spi if it is an // instance of SignatureSpi but not Signature boolean r = (instance instanceof SignatureSpi) && (instance instanceof Signature == false); if ((debug != null) && (r == false)) { debug.println("Not a SignatureSpi " + className); debug.println("Delayed provider selection may not be " + "available for algorithm " + s.getAlgorithm()); } result = Boolean.valueOf(r); signatureInfo.put(className, result); } catch (Exception e) { // something is wrong, assume not an SPI return false; } } return result.booleanValue(); } /** * Returns a Signature object that implements the specified signature * algorithm. * * <p> A new Signature object encapsulating the * SignatureSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * * <p> Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. * See the Signature section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new Signature object. * * @exception NoSuchAlgorithmException if a SignatureSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static Signature getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { // exception compatibility with existing code if ((provider == null) || (provider.length() == 0)) { throw new IllegalArgumentException("missing provider"); } Provider p = Security.getProvider(provider); if (p == null) { throw new NoSuchProviderException ("no such provider: " + provider); } return getInstanceRSA(p); } Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); } /** * Returns a Signature object that implements the specified * signature algorithm. * * <p> A new Signature object encapsulating the * SignatureSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the name of the algorithm requested. * See the Signature section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard algorithm names. * * @param provider the provider. * * @return the new Signature object. * * @exception NoSuchAlgorithmException if a SignatureSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the provider is null. * * @see Provider * * @since 1.4 */ public static Signature getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) { // exception compatibility with existing code if (provider == null) { throw new IllegalArgumentException("missing provider"); } return getInstanceRSA(provider); } Instance instance = GetInstance.getInstance ("Signature", SignatureSpi.class, algorithm, provider); return getInstance(instance, algorithm); } // return an implementation for NONEwithRSA, which is a special case // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper private static Signature getInstanceRSA(Provider p) throws NoSuchAlgorithmException { // try Signature first Service s = p.getService("Signature", RSA_SIGNATURE); if (s != null) { Instance instance = GetInstance.getInstance(s, SignatureSpi.class); return getInstance(instance, RSA_SIGNATURE); } // check Cipher try { Cipher c = Cipher.getInstance(RSA_CIPHER, p); return new Delegate(new CipherAdapter(c), RSA_SIGNATURE); } catch (GeneralSecurityException e) { // throw Signature style exception message to avoid confusion, // but append Cipher exception as cause throw new NoSuchAlgorithmException("no such algorithm: " + RSA_SIGNATURE + " for provider " + p.getName(), e); } } /** * Returns the provider of this signature object. * * @return the provider of this signature object */ public final Provider getProvider() { chooseFirstProvider(); return this.provider; } void chooseFirstProvider() { // empty, overridden in Delegate } /** * Initializes this object for verification. If this method is called * again with a different argument, it negates the effect * of this call. * * @param publicKey the public key of the identity whose signature is * going to be verified. * * @exception InvalidKeyException if the key is invalid. */ public final void initVerify(PublicKey publicKey) throws InvalidKeyException { engineInitVerify(publicKey); state = VERIFY; } /** * Initializes this object for verification, using the public key from * the given certificate. * <p>If the certificate is of type X.509 and has a <i>key usage</i> * extension field marked as critical, and the value of the <i>key usage</i> * extension field implies that the public key in * the certificate and its corresponding private key are not * supposed to be used for digital signatures, an * <code>InvalidKeyException</code> is thrown. * * @param certificate the certificate of the identity whose signature is * going to be verified. * * @exception InvalidKeyException if the public key in the certificate * is not encoded properly or does not include required parameter * information or cannot be used for digital signature purposes. * @since 1.3 */ public final void initVerify(Certificate certificate) throws InvalidKeyException { // If the certificate is of type X509Certificate, // we should check whether it has a Key Usage // extension marked as critical. if (certificate instanceof java.security.cert.X509Certificate) { // Check whether the cert has a key usage extension // marked as a critical extension. // The OID for KeyUsage extension is 2.5.29.15. X509Certificate cert = (X509Certificate)certificate; Set<String> critSet = cert.getCriticalExtensionOIDs(); if (critSet != null && !critSet.isEmpty() && critSet.contains("2.5.29.15")) { boolean[] keyUsageInfo = cert.getKeyUsage(); // keyUsageInfo[0] is for digitalSignature. if ((keyUsageInfo != null) && (keyUsageInfo[0] == false)) throw new InvalidKeyException("Wrong key usage"); } } PublicKey publicKey = certificate.getPublicKey(); engineInitVerify(publicKey); state = VERIFY; } /** * Initialize this object for signing. If this method is called