Showing the changes to java/pkg/java/security/Signature.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,1293 @@ | |||
| 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 | } | ||