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