History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/security/Signature.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/security/Signature.java+1293−0
@@ -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+}