KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > Signature


1 /*
2  * @(#)Signature.java 1.99 04/05/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7   
8 package java.security;
9
10 import java.security.spec.AlgorithmParameterSpec JavaDoc;
11 import java.util.*;
12 import java.util.concurrent.ConcurrentHashMap JavaDoc;
13 import java.io.*;
14 import java.security.cert.Certificate JavaDoc;
15 import java.security.cert.X509Certificate JavaDoc;
16
17 import java.nio.ByteBuffer JavaDoc;
18
19 import java.security.Provider.Service;
20
21 import javax.crypto.Cipher;
22 import javax.crypto.CipherSpi;
23 import javax.crypto.IllegalBlockSizeException;
24 import javax.crypto.BadPaddingException;
25 import javax.crypto.NoSuchPaddingException;
26
27 import sun.security.util.Debug;
28 import sun.security.jca.*;
29 import sun.security.jca.GetInstance.Instance;
30
31 /**
32  * This Signature class is used to provide applications the functionality
33  * of a digital signature algorithm. Digital signatures are used for
34  * authentication and integrity assurance of digital data.
35  *
36  * <p> The signature algorithm can be, among others, the NIST standard
37  * DSA, using DSA and SHA-1. The DSA algorithm using the
38  * SHA-1 message digest algorithm can be specified as <tt>SHA1withDSA</tt>.
39  * In the case of RSA, there are multiple choices for the message digest
40  * algorithm, so the signing algorithm could be specified as, for example,
41  * <tt>MD2withRSA</tt>, <tt>MD5withRSA</tt>, or <tt>SHA1withRSA</tt>.
42  * The algorithm name must be specified, as there is no default.
43  *
44  * <p>Like other algorithm-based classes in Java Security, Signature
45  * provides implementation-independent algorithms, whereby a caller
46  * (application code) requests a particular signature algorithm
47  * and is handed back a properly initialized Signature object. It is
48  * also possible, if desired, to request a particular algorithm from a
49  * particular provider. See the <code>getInstance </code> methods.
50  *
51  * <p>Thus, there are two ways to request a Signature algorithm object: by
52  * specifying either just an algorithm name, or both an algorithm name
53  * and a package provider. <ul>
54  *
55  * <li>If just an algorithm name is specified, the system will
56  * determine if there is an implementation of the algorithm requested
57  * available in the environment, and if there is more than one, if
58  * there is a preferred one.<p>
59  *
60  * <li>If both an algorithm name and a package provider are specified,
61  * the system will determine if there is an implementation of the
62  * algorithm in the package requested, and throw an exception if there
63  * is not.
64  *
65  * </ul>
66  *
67  * <p>A Signature object can be used to generate and verify digital
68  * signatures.
69  *
70  * <p>There are three phases to the use of a Signature object for
71  * either signing data or verifying a signature:<ol>
72  *
73  * <li>Initialization, with either
74  *
75  * <ul>
76  *
77  * <li>a public key, which initializes the signature for
78  * verification (see {@link #initVerify(PublicKey) initVerify}), or
79  *
80  * <li>a private key (and optionally a Secure Random Number Generator),
81  * which initializes the signature for signing
82  * (see {@link #initSign(PrivateKey)}
83  * and {@link #initSign(PrivateKey, SecureRandom)}).
84  *
85  * </ul><p>
86  *
87  * <li>Updating<p>
88  *
89  * <p>Depending on the type of initialization, this will update the
90  * bytes to be signed or verified. See the
91  * {@link #update(byte) update} methods.<p>
92  *
93  * <li>Signing or Verifying a signature on all updated bytes. See the
94  * {@link #sign() sign} methods and the {@link #verify(byte[]) verify}
95  * method.
96  *
97  * </ol>
98  *
99  * <p>Note that this class is abstract and extends from
100  * <code>SignatureSpi</code> for historical reasons.
101  * Application developers should only take notice of the methods defined in
102  * this <code>Signature</code> class; all the methods in
103  * the superclass are intended for cryptographic service providers who wish to
104  * supply their own implementations of digital signature algorithms.
105  *
106  * @author Benjamin Renaud
107  *
108  * @version 1.99, 05/18/04
109  */

110
111 public abstract class Signature extends SignatureSpi JavaDoc {
112
113     private static final Debug debug =
114             Debug.getInstance("jca", "Signature");
115     
116     /*
117      * The algorithm for this signature object.
118      * This value is used to map an OID to the particular algorithm.
119      * The mapping is done in AlgorithmObject.algOID(String algorithm)
120      */

121     private String JavaDoc algorithm;
122
123     // The provider
124
Provider JavaDoc provider;
125
126     /**
127      * Possible {@link #state} value, signifying that
128      * this signature object has not yet been initialized.
129      */

130     protected final static int UNINITIALIZED = 0;
131        
132     /**
133      * Possible {@link #state} value, signifying that
134      * this signature object has been initialized for signing.
135      */

136     protected final static int SIGN = 2;
137        
138     /**
139      * Possible {@link #state} value, signifying that
140      * this signature object has been initialized for verification.
141      */

142     protected final static int VERIFY = 3;
143
144     /**
145      * Current state of this signature object.
146      */

147     protected int state = UNINITIALIZED;
148
149     /**
150      * Creates a Signature object for the specified algorithm.
151      *
152      * @param algorithm the standard string name of the algorithm.
153      * See Appendix A in the <a HREF=
154      * "../../../guide/security/CryptoSpec.html#AppA">
155      * Java Cryptography Architecture API Specification &amp; Reference </a>
156      * for information about standard algorithm names.
157      */

158     protected Signature(String JavaDoc algorithm) {
159     this.algorithm = algorithm;
160     }
161     
162     // name of the special signature alg
163
private final static String JavaDoc RSA_SIGNATURE = "NONEwithRSA";
164
165     // name of the equivalent cipher alg
166
private final static String JavaDoc RSA_CIPHER = "RSA/ECB/PKCS1Padding";
167     
168     // all the services we need to lookup for compatibility with Cipher
169
private final static List<ServiceId> rsaIds = Arrays.asList(
170     new ServiceId[] {
171         new ServiceId("Signature", "NONEwithRSA"),
172         new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"),
173         new ServiceId("Cipher", "RSA/ECB"),
174         new ServiceId("Cipher", "RSA//PKCS1Padding"),
175         new ServiceId("Cipher", "RSA"),
176     }
177     );
178
179     /**
180      * Generates a Signature object that implements the specified digest
181      * algorithm. If the default provider package
182      * provides an implementation of the requested digest algorithm,
183      * an instance of Signature containing that implementation is returned.
184      * If the algorithm is not available in the default
185      * package, other packages are searched.
186      *
187      * @param algorithm the standard name of the algorithm requested.
188      * See Appendix A in the <a HREF=
189      * "../../../guide/security/CryptoSpec.html#AppA">
190      * Java Cryptography Architecture API Specification &amp; Reference </a>
191      * for information about standard algorithm names.
192      *
193      * @return the new Signature object.
194      *
195      * @exception NoSuchAlgorithmException if the algorithm is
196      * not available in the environment.
197      */

198     public static Signature JavaDoc getInstance(String JavaDoc algorithm)
199         throws NoSuchAlgorithmException JavaDoc {
200     List list;
201     if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
202         list = GetInstance.getServices(rsaIds);
203     } else {
204         list = GetInstance.getServices("Signature", algorithm);
205     }
206     Iterator t = list.iterator();
207     if (t.hasNext() == false) {
208         throw new NoSuchAlgorithmException JavaDoc
209             (algorithm + " Signature not available");
210     }
211     // try services until we find an Spi or a working Signature subclass
212
NoSuchAlgorithmException JavaDoc failure;
213     do {
214         Service s = (Service)t.next();
215         if (isSpi(s)) {
216         return new Delegate(s, t, algorithm);
217         } else {
218         // must be a subclass of Signature, disable dynamic selection
219
try {
220             Instance instance =
221                 GetInstance.getInstance(s, SignatureSpi JavaDoc.class);
222             return getInstance(instance, algorithm);
223         } catch (NoSuchAlgorithmException JavaDoc e) {
224             failure = e;
225         }
226         }
227     } while (t.hasNext());
228     throw failure;
229     }
230     
231     private static Signature JavaDoc getInstance(Instance instance, String JavaDoc algorithm) {
232     Signature JavaDoc sig;
233     if (instance.impl instanceof Signature JavaDoc) {
234         sig = (Signature JavaDoc)instance.impl;
235     } else {
236         SignatureSpi JavaDoc spi = (SignatureSpi JavaDoc)instance.impl;
237         sig = new Delegate(spi, algorithm);
238     }
239     sig.provider = instance.provider;
240     return sig;
241     }
242     
243     private final static Map JavaDoc<String JavaDoc,Boolean JavaDoc> signatureInfo;
244     
245     static {
246         signatureInfo = new ConcurrentHashMap JavaDoc<String JavaDoc,Boolean JavaDoc>();
247     Boolean JavaDoc TRUE = Boolean.TRUE;
248     // pre-initialize with values for our SignatureSpi implementations
249
signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE);
250     signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE);
251     signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE);
252     signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE);
253     signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE);
254     signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE);
255     signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE);
256     signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE);
257     signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE);
258     signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE);
259     }
260     
261     private static boolean isSpi(Service s) {
262     if (s.getType().equals("Cipher")) {
263         // must be a CipherSpi, which we can wrap with the CipherAdapter
264
return true;
265     }
266     String JavaDoc className = s.getClassName();
267     Boolean JavaDoc result = signatureInfo.get(className);
268     if (result == null) {
269         try {
270         Object JavaDoc instance = s.newInstance(null);
271         // Signature extends SignatureSpi
272
// so it is a "real" Spi if it is an
273
// instance of SignatureSpi but not Signature
274
boolean r = (instance instanceof SignatureSpi JavaDoc)
275                 && (instance instanceof Signature JavaDoc == false);
276         if ((debug != null) && (r == false)) {
277             debug.println("Not a SignatureSpi " + className);
278             debug.println("Delayed provider selection may not be "
279                 + "available for algorithm " + s.getAlgorithm());
280         }
281         result = Boolean.valueOf(r);
282         signatureInfo.put(className, result);
283         } catch (Exception JavaDoc e) {
284         // something is wrong, assume not an SPI
285
return false;
286         }
287     }
288     return result.booleanValue();
289     }
290
291     /**
292      * Generates a Signature object implementing the specified
293      * algorithm, as supplied from the specified provider, if such an
294      * algorithm is available from the provider.
295      *
296      * @param algorithm the name of the algorithm requested.
297      * See Appendix A in the <a HREF=
298      * "../../../guide/security/CryptoSpec.html#AppA">
299      * Java Cryptography Architecture API Specification &amp; Reference </a>
300      * for information about standard algorithm names.
301      *
302      * @param provider the name of the provider.
303      *
304      * @return the new Signature object.
305      *
306      * @exception NoSuchAlgorithmException if the algorithm is
307      * not available in the package supplied by the requested
308      * provider.
309      *
310      * @exception NoSuchProviderException if the provider is not
311      * available in the environment.
312      *
313      * @exception IllegalArgumentException if the provider name is null
314      * or empty.
315      *
316      * @see Provider
317      */

318     public static Signature JavaDoc getInstance(String JavaDoc algorithm, String JavaDoc provider)
319         throws NoSuchAlgorithmException JavaDoc, NoSuchProviderException JavaDoc {
320     if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
321         // exception compatibility with existing code
322
if ((provider == null) || (provider.length() == 0)) {
323         throw new IllegalArgumentException JavaDoc("missing provider");
324         }
325         Provider JavaDoc p = Security.getProvider(provider);
326         if (p == null) {
327         throw new NoSuchProviderException JavaDoc
328             ("no such provider: " + provider);
329         }
330         return getInstanceRSA(p);
331     }
332     Instance instance = GetInstance.getInstance
333         ("Signature", SignatureSpi JavaDoc.class, algorithm, provider);
334     return getInstance(instance, algorithm);
335     }
336     
337     /**
338      * Generates a Signature object implementing the specified
339      * algorithm, as supplied from the specified provider, if such an
340      * algorithm is available from the provider. Note: the
341      * <code>provider</code> doesn't have to be registered.
342      *
343      * @param algorithm the name of the algorithm requested.
344      * See Appendix A in the <a HREF=
345      * "../../../guide/security/CryptoSpec.html#AppA">
346      * Java Cryptography Architecture API Specification &amp; Reference </a>
347      * for information about standard algorithm names.
348      *
349      * @param provider the provider.
350      *
351      * @return the new Signature object.
352      *
353      * @exception NoSuchAlgorithmException if the algorithm is
354      * not available in the package supplied by the requested
355      * provider.
356      *
357      * @exception IllegalArgumentException if the <code>provider</code> is
358      * null.
359      *
360      * @see Provider
361      *
362      * @since 1.4
363      */

364     public static Signature JavaDoc getInstance(String JavaDoc algorithm, Provider JavaDoc provider)
365         throws NoSuchAlgorithmException JavaDoc {
366     if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
367         // exception compatibility with existing code
368
if (provider == null) {
369         throw new IllegalArgumentException JavaDoc("missing provider");
370         }
371         return getInstanceRSA(provider);
372     }
373     Instance instance = GetInstance.getInstance
374         ("Signature", SignatureSpi JavaDoc.class, algorithm, provider);
375     return getInstance(instance, algorithm);
376     }
377
378     // return an implementation for NONEwithRSA, which is a special case
379
// because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper
380
private static Signature JavaDoc getInstanceRSA(Provider JavaDoc p)
381         throws NoSuchAlgorithmException JavaDoc {
382     // try Signature first
383
Service s = p.getService("Signature", RSA_SIGNATURE);
384     if (s != null) {
385         Instance instance = GetInstance.getInstance(s, SignatureSpi JavaDoc.class);
386         return getInstance(instance, RSA_SIGNATURE);
387     }
388     // check Cipher
389
try {
390         Cipher c = Cipher.getInstance(RSA_CIPHER, p);
391         return new Delegate(new CipherAdapter(c), RSA_SIGNATURE);
392     } catch (GeneralSecurityException JavaDoc e) {
393         // throw Signature style exception message to avoid confusion,
394
// but append Cipher exception as cause
395
throw new NoSuchAlgorithmException JavaDoc("no such algorithm: "
396         + RSA_SIGNATURE + " for provider " + p.getName(), e);
397     }
398     }
399
400     /**
401      * Returns the provider of this signature object.
402      *
403      * @return the provider of this signature object
404      */

405     public final Provider JavaDoc getProvider() {
406     chooseFirstProvider();
407     return this.provider;
408     }
409     
410     void chooseFirstProvider() {
411     // empty, overridden in Delegate
412
}
413
414     /**
415      * Initializes this object for verification. If this method is called
416      * again with a different argument, it negates the effect
417      * of this call.
418      *
419      * @param publicKey the public key of the identity whose signature is
420      * going to be verified.
421      *
422      * @exception InvalidKeyException if the key is invalid.
423      */

424     public final void initVerify(PublicKey JavaDoc publicKey)
425         throws InvalidKeyException JavaDoc {
426     engineInitVerify(publicKey);
427     state = VERIFY;
428     }
429
430     /**
431      * Initializes this object for verification, using the public key from
432      * the given certificate.
433      * <p>If the certificate is of type X.509 and has a <i>key usage</i>
434      * extension field marked as critical, and the value of the <i>key usage</i>
435      * extension field implies that the public key in
436      * the certificate and its corresponding private key are not
437      * supposed to be used for digital signatures, an
438      * <code>InvalidKeyException</code> is thrown.
439      *
440      * @param certificate the certificate of the identity whose signature is
441      * going to be verified.
442      *
443      * @exception InvalidKeyException if the public key in the certificate
444      * is not encoded properly or does not include required parameter
445      * information or cannot be used for digital signature purposes.
446      */

447     public final void initVerify(Certificate JavaDoc certificate)
448         throws InvalidKeyException JavaDoc {
449     // If the certificate is of type X509Certificate,
450
// we should check whether it has a Key Usage
451
// extension marked as critical.
452
if (certificate instanceof java.security.cert.X509Certificate JavaDoc) {
453         // Check whether the cert has a key usage extension
454
// marked as a critical extension.
455
// The OID for KeyUsage extension is 2.5.29.15.
456
X509Certificate JavaDoc cert = (X509Certificate JavaDoc)certificate;
457         Set critSet = cert.getCriticalExtensionOIDs();
458
459         if (critSet != null && !critSet.isEmpty()
460         && critSet.contains("2.5.29.15")) {
461         boolean[] keyUsageInfo = cert.getKeyUsage();
462         // keyUsageInfo[0] is for digitalSignature.
463
if ((keyUsageInfo != null) && (keyUsageInfo[0] == false))
464             throw new InvalidKeyException JavaDoc("Wrong key usage");
465         }
466     }
467         
468     PublicKey JavaDoc publicKey = certificate.getPublicKey();
469     engineInitVerify(publicKey);
470     state = VERIFY;
471     }
472
473     /**
474      * Initialize this object for signing. If this method is called
475      * again with a different argument, it negates the effect
476      * of this call.
477      *
478      * @param privateKey the private key of the identity whose signature
479      * is going to be generated.
480      *
481      * @exception InvalidKeyException if the key is invalid.
482      */

483     public final void initSign(PrivateKey JavaDoc privateKey)
484         throws InvalidKeyException JavaDoc {
485     engineInitSign(privateKey);
486     state = SIGN;
487     }
488
489     /**
490      * Initialize this object for signing. If this method is called
491      * again with a different argument, it negates the effect
492      * of this call.
493      *
494      * @param privateKey the private key of the identity whose signature
495      * is going to be generated.
496      *
497      * @param random the source of randomness for this signature.
498      *
499      * @exception InvalidKeyException if the key is invalid.
500      */

501     public final void initSign(PrivateKey JavaDoc privateKey, SecureRandom JavaDoc random)
502         throws InvalidKeyException JavaDoc {
503     engineInitSign(privateKey, random);
504     state = SIGN;
505     }
506
507     /**
508      * Returns the signature bytes of all the data updated.
509      * The format of the signature depends on the underlying
510      * signature scheme.
511      *
512      * <p>A call to this method resets this signature object to the state
513      * it was in when previously initialized for signing via a
514      * call to <code>initSign(PrivateKey)</code>. That is, the object is
515      * reset and available to generate another signature from the same
516      * signer, if desired, via new calls to <code>update</code> and
517      * <code>sign</code>.
518      *
519      * @return the signature bytes of the signing operation's result.
520      *
521      * @exception SignatureException if this signature object is not
522      * initialized properly or if this signature algorithm is unable to
523      * process the input data provided.
524      */

525     public final byte[] sign() throws SignatureException JavaDoc {
526     if (state == SIGN) {
527         return engineSign();
528     }
529     throw new SignatureException JavaDoc("object not initialized for " +
530                      "signing");
531     }
532
533     /**
534      * Finishes the signature operation and stores the resulting signature
535      * bytes in the provided buffer <code>outbuf</code>, starting at
536      * <code>offset</code>.
537      * The format of the signature depends on the underlying
538      * signature scheme.
539      *
540      * <p>This signature object is reset to its initial state (the state it
541      * was in after a call to one of the <code>initSign</code> methods) and
542      * can be reused to generate further signatures with the same private key.
543      *
544      * @param outbuf buffer for the signature result.
545      *
546      * @param offset offset into <code>outbuf</code> where the signature is
547      * stored.
548      *
549      * @param len number of bytes within <code>outbuf</code> allotted for the
550      * signature.
551      *
552      * @return the number of bytes placed into <code>outbuf</code>.
553      *
554      * @exception SignatureException if this signature object is not
555      * initialized properly, if this signature algorithm is unable to
556      * process the input data provided, or if <code>len</code> is less
557      * than the actual signature length.
558      *
559      * @since 1.2
560      */

561     public final int sign(byte[] outbuf, int offset, int len)
562     throws SignatureException JavaDoc {
563     if (outbuf == null) {
564         throw new IllegalArgumentException JavaDoc("No output buffer given");
565     }
566     if (outbuf.length - offset < len) {
567         throw new IllegalArgumentException JavaDoc
568         ("Output buffer too small for specified offset and length");
569     }
570     if (state != SIGN) {
571         throw new SignatureException JavaDoc("object not initialized for " +
572                      "signing");
573     }
574     return engineSign(outbuf, offset, len);
575     }
576
577     /**
578      * Verifies the passed-in signature.
579      *
580      * <p>A call to this method resets this signature object to the state
581      * it was in when previously initialized for verification via a
582      * call to <code>initVerify(PublicKey)</code>. That is, the object is
583      * reset and available to verify another signature from the identity
584      * whose public key was specified in the call to <code>initVerify</code>.
585      *
586      * @param signature the signature bytes to be verified.
587      *
588      * @return true if the signature was verified, false if not.
589      *
590      * @exception SignatureException if this signature object is not
591      * initialized properly, the passed-in signature is improperly
592      * encoded or of the wrong type, if this signature algorithm is unable to
593      * process the input data provided, etc.
594      */

595     public final boolean verify(byte[] signature) throws SignatureException JavaDoc {
596     if (state == VERIFY) {
597         return engineVerify(signature);
598     }
599     throw new SignatureException JavaDoc("object not initialized for " +
600                      "verification");
601     }
602
603     /**
604      * Verifies the passed-in signature in the specified array
605      * of bytes, starting at the specified offset.
606      *
607      * <p>A call to this method resets this signature object to the state
608      * it was in when previously initialized for verification via a
609      * call to <code>initVerify(PublicKey)</code>. That is, the object is
610      * reset and available to verify another signature from the identity
611      * whose public key was specified in the call to <code>initVerify</code>.
612      *
613      *
614      * @param signature the signature bytes to be verified.
615      * @param offset the offset to start from in the array of bytes.
616      * @param length the number of bytes to use, starting at offset.
617      *
618      * @return true if the signature was verified, false if not.
619      *
620      * @exception SignatureException if this signature object is not
621      * initialized properly, the passed-in signature is improperly
622      * encoded or of the wrong type, if this signature algorithm is unable to
623      * process the input data provided, etc.
624      * @exception IllegalArgumentException if the <code>signature</code>
625      * byte array is null, or the <code>offset</code> or <code>length</code>
626      * is less than 0, or the sum of the <code>offset</code> and
627      * <code>length</code> is greater than the length of the
628      * <code>signature</code> byte array.
629      */

630     public final boolean verify(byte[] signature, int offset, int length)
631     throws SignatureException JavaDoc {
632     if (state == VERIFY) {
633         if ((signature == null) || (offset < 0) || (length < 0) ||
634         (offset + length > signature.length)) {
635         throw new IllegalArgumentException JavaDoc("Bad arguments");
636         }
637
638         return engineVerify(signature, offset, length);
639     }
640     throw new SignatureException JavaDoc("object not initialized for " +
641                      "verification");
642     }
643
644     /**
645      * Updates the data to be signed or verified by a byte.
646      *
647      * @param b the byte to use for the update.
648      *
649      * @exception SignatureException if this signature object is not
650      * initialized properly.
651      */

652     public final void update(byte b) throws SignatureException JavaDoc {
653     if (state == VERIFY || state == SIGN) {
654         engineUpdate(b);
655     } else {
656         throw new SignatureException JavaDoc("object not initialized for "
657                      + "signature or verification");
658     }
659     }
660
661     /**
662      * Updates the data to be signed or verified, using the specified
663      * array of bytes.
664      *
665      * @param data the byte array to use for the update.
666      *
667      * @exception SignatureException if this signature object is not
668      * initialized properly.
669      */

670     public final void update(byte[] data) throws SignatureException JavaDoc {
671     update(data, 0, data.length);
672     }
673
674     /**
675      * Updates the data to be signed or verified, using the specified
676      * array of bytes, starting at the specified offset.
677      *
678      * @param data the array of bytes.
679      * @param off the offset to start from in the array of bytes.
680      * @param len the number of bytes to use, starting at offset.
681      *
682      * @exception SignatureException if this signature object is not
683      * initialized properly.
684      */

685     public final void update(byte[] data, int off, int len)
686         throws SignatureException JavaDoc {
687     if (state == SIGN || state == VERIFY) {
688         engineUpdate(data, off, len);
689     } else {
690         throw new SignatureException JavaDoc("object not initialized for "
691                      + "signature or verification");
692     }
693     }
694
695     /**
696      * Updates the data to be signed or verified using the specified
697      * ByteBuffer. Processes the <code>data.remaining()</code> bytes
698      * starting at at <code>data.position()</code>.
699      * Upon return, the buffer's position will be equal to its limit;
700      * its limit will not have changed.
701      *
702      * @param data the ByteBuffer
703      *
704      * @exception SignatureException if this signature object is not
705      * initialized properly.
706      * @since 1.5
707      */

708     public final void update(ByteBuffer JavaDoc data) throws SignatureException JavaDoc {
709     if ((state != SIGN) && (state != VERIFY)) {
710         throw new SignatureException JavaDoc("object not initialized for "
711                      + "signature or verification");
712     }
713     if (data == null) {
714         throw new NullPointerException JavaDoc();
715     }
716     engineUpdate(data);
717     }
718
719     /**
720      * Returns the name of the algorithm for this signature object.
721      *
722      * @return the name of the algorithm for this signature object.
723      */

724     public final String JavaDoc getAlgorithm() {
725     return this.algorithm;
726     }
727
728     /**
729      * Returns a string representation of this signature object,
730      * providing information that includes the state of the object
731      * and the name of the algorithm used.
732      *
733      * @return a string representation of this signature object.
734      */

735     public String JavaDoc toString() {
736     String JavaDoc initState = "";
737     switch (state) {
738     case UNINITIALIZED:
739         initState = "<not initialized>";
740         break;
741     case VERIFY:
742         initState = "<initialized for verifying>";
743         break;
744     case SIGN:
745         initState = "<initialized for signing>";
746         break;
747     }
748     return "Signature object: " + getAlgorithm() + initState;
749     }
750
751     /**
752      * Sets the specified algorithm parameter to the specified value.
753      * This method supplies a general-purpose mechanism through
754      * which it is possible to set the various parameters of this object.
755      * A parameter may be any settable parameter for the algorithm, such as
756      * a parameter size, or a source of random bits for signature generation
757      * (if appropriate), or an indication of whether or not to perform
758      * a specific but optional computation. A uniform algorithm-specific
759      * naming scheme for each parameter is desirable but left unspecified
760      * at this time.
761      *
762      * @param param the string identifier of the parameter.
763      * @param value the parameter value.
764      *
765      * @exception InvalidParameterException if <code>param</code> is an
766      * invalid parameter for this signature algorithm engine,
767      * the parameter is already set
768      * and cannot be set again, a security exception occurs, and so on.
769      *
770      * @see #getParameter
771      *
772      * @deprecated Use
773      * {@link #setParameter(java.security.spec.AlgorithmParameterSpec)
774      * setParameter}.
775      */

776     @Deprecated JavaDoc
777     public final void setParameter(String JavaDoc param, Object JavaDoc value)
778         throws InvalidParameterException JavaDoc {
779     engineSetParameter(param, value);
780     }
781
782     /**
783      * Initializes this signature engine with the specified parameter set.
784      *
785      * @param params the parameters
786      *
787      * @exception InvalidAlgorithmParameterException if the given parameters
788      * are inappropriate for this signature engine
789      *
790      * @see #getParameters
791      */

792     public final void setParameter(AlgorithmParameterSpec JavaDoc params)
793         throws InvalidAlgorithmParameterException JavaDoc {
794     engineSetParameter(params);
795     }
796
797     /**
798      * Returns the parameters used with this signature object.
799      *
800      * <p>The returned parameters may be the same that were used to initialize
801      * this signature, or may contain a combination of default and randomly
802      * generated parameter values used by the underlying signature
803      * implementation if this signature requires algorithm parameters but
804      * was not initialized with any.
805      *
806      * @return the parameters used with this signature, or null if this
807      * signature does not use any parameters.
808      *
809      * @see #setParameter(AlgorithmParameterSpec)
810      */

811     public final AlgorithmParameters JavaDoc getParameters() {
812     return engineGetParameters();
813     }
814
815     /**
816      * Gets the value of the specified algorithm parameter. This method
817      * supplies a general-purpose mechanism through which it is possible to
818      * get the various parameters of this object. A parameter may be any
819      * settable parameter for the algorithm, such as a parameter size, or
820      * a source of random bits for signature generation (if appropriate),
821      * or an indication of whether or not to perform a specific but optional
822      * computation. A uniform algorithm-specific naming scheme for each
823      * parameter is desirable but left unspecified at this time.
824      *
825      * @param param the string name of the parameter.
826      *
827      * @return the object that represents the parameter value, or null if
828      * there is none.
829      *
830      * @exception InvalidParameterException if <code>param</code> is an invalid
831      * parameter for this engine, or another exception occurs while
832      * trying to get this parameter.
833      *
834      * @see #setParameter(String, Object)
835      *
836      * @deprecated
837      */

838     @Deprecated JavaDoc
839     public final Object JavaDoc getParameter(String JavaDoc param)
840         throws InvalidParameterException JavaDoc {
841     return engineGetParameter(param);
842     }
843
844     /**
845      * Returns a clone if the implementation is cloneable.
846      *
847      * @return a clone if the implementation is cloneable.
848      *
849      * @exception CloneNotSupportedException if this is called
850      * on an implementation that does not support <code>Cloneable</code>.
851      */

852     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
853     if (this instanceof Cloneable JavaDoc) {
854         return super.clone();
855     } else {
856         throw new CloneNotSupportedException JavaDoc();
857     }
858     }
859     
860     /*
861      * The following class allows providers to extend from SignatureSpi
862      * rather than from Signature. It represents a Signature with an
863      * encapsulated, provider-supplied SPI object (of type SignatureSpi).
864      * If the provider implementation is an instance of SignatureSpi, the
865      * getInstance() methods above return an instance of this class, with
866      * the SPI object encapsulated.
867      *
868      * Note: All SPI methods from the original Signature class have been
869      * moved up the hierarchy into a new class (SignatureSpi), which has
870      * been interposed in the hierarchy between the API (Signature)
871      * and its original parent (Object).
872      */

873
874     private static class Delegate extends Signature JavaDoc {
875
876     // The provider implementation (delegate)
877
// filled in once the provider is selected
878
private SignatureSpi JavaDoc sigSpi;
879     
880     // lock for mutex during provider selection
881
private final Object JavaDoc lock;
882
883     // next service to try in provider selection
884
// null once provider is selected
885
private Service firstService;
886     
887     // remaining services to try in provider selection
888
// null once provider is selected
889
private Iterator serviceIterator;
890     
891     // constructor
892
Delegate(SignatureSpi JavaDoc sigSpi, String JavaDoc algorithm) {
893         super(algorithm);
894         this.sigSpi = sigSpi;
895         this.lock = null; // no lock needed
896
}
897     
898     // used with delayed provider selection
899
Delegate(Service service, Iterator iterator, String JavaDoc algorithm) {
900         super(algorithm);
901         this.firstService = service;
902         this.serviceIterator = iterator;
903         this.lock = new Object JavaDoc();
904     }
905     
906     /*
907      * Returns a clone if the delegate is cloneable.
908      *
909      * @return a clone if the delegate is cloneable.
910      *
911      * @exception CloneNotSupportedException if this is called on a
912      * delegate that does not support <code>Cloneable</code>.
913      */

914     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
915         chooseFirstProvider();
916         if (sigSpi instanceof Cloneable JavaDoc) {
917         SignatureSpi JavaDoc sigSpiClone = (SignatureSpi JavaDoc)sigSpi.clone();
918         // Because 'algorithm' and 'provider' are private
919
// members of our supertype, we must perform a cast to
920
// access them.
921
Signature JavaDoc that =
922             new Delegate(sigSpiClone, ((Signature JavaDoc)this).algorithm);
923         that.provider = ((Signature JavaDoc)this).provider;
924         return that;
925         } else {
926         throw new CloneNotSupportedException JavaDoc();
927         }
928     }
929     
930     private static SignatureSpi JavaDoc newInstance(Service s)
931         throws NoSuchAlgorithmException JavaDoc {
932         if (s.getType().equals("Cipher")) {
933         // must be NONEwithRSA
934
try {
935             Cipher c = Cipher.getInstance(RSA_CIPHER, s.getProvider());
936             return new CipherAdapter(c);
937         } catch (NoSuchPaddingException e) {
938             throw new NoSuchAlgorithmException JavaDoc(e);
939         }
940         } else {
941         Object JavaDoc o = s.newInstance(null);
942         if (o instanceof SignatureSpi JavaDoc == false) {
943             throw new NoSuchAlgorithmException JavaDoc
944             ("Not a SignatureSpi: " + o.getClass().getName());
945         }
946         return (SignatureSpi JavaDoc)o;
947         }
948     }
949
950     // max number of debug warnings to print from chooseFirstProvider()
951
private static int warnCount = 10;
952
953     /**
954      * Choose the Spi from the first provider available. Used if
955      * delayed provider selection is not possible because initSign()/
956      * initVerify() is not the first method called.
957      */

958     void chooseFirstProvider() {
959         if (sigSpi != null) {
960         return;
961         }
962         synchronized (lock) {
963         if (sigSpi != null) {
964             return;
965         }
966         if (debug != null) {
967             int w = --warnCount;
968             if (w >= 0) {
969             debug.println("Signature.init() not first method "
970                 + "called, disabling delayed provider selection");
971             if (w == 0) {
972                 debug.println("Further warnings of this type will "
973                     + "be suppressed");
974             }
975             new Exception JavaDoc("Call trace").printStackTrace();
976             }
977         }
978         Exception JavaDoc lastException = null;
979         while ((firstService != null) || serviceIterator.hasNext()) {
980             Service s;
981             if (firstService != null) {
982             s = firstService;
983             firstService = null;
984             } else {
985             s = (Service)serviceIterator.next();
986             }
987             if (isSpi(s) == false) {
988             continue;
989             }
990             try {
991             sigSpi = newInstance(s);
992             provider = s.getProvider();
993             // not needed any more
994
firstService = null;
995             serviceIterator = null;
996             return;
997             } catch (NoSuchAlgorithmException JavaDoc e) {
998             lastException = e;
999             }
1000        }
1001        ProviderException JavaDoc e = new ProviderException JavaDoc
1002            ("Could not construct SignatureSpi instance");
1003        if (lastException != null) {
1004            e.initCause(lastException);
1005        }
1006        throw e;
1007        }
1008    }
1009    
1010    private void chooseProvider(int type, Key JavaDoc key, SecureRandom JavaDoc random)
1011        throws InvalidKeyException JavaDoc {
1012        synchronized (lock) {
1013        if (sigSpi != null) {
1014            init(sigSpi, type, key, random);
1015            return;
1016        }
1017        Exception JavaDoc lastException = null;
1018        while ((firstService != null) || serviceIterator.hasNext()) {
1019            Service s;
1020            if (firstService != null) {
1021            s = firstService;
1022            firstService = null;
1023            } else {
1024            s = (Service)serviceIterator.next();
1025            }
1026            // if provider says it does not support this key, ignore it
1027
if (s.supportsParameter(key) == false) {
1028            continue;
1029            }
1030            // if instance is not a SignatureSpi, ignore it
1031
if (isSpi(s) == false) {
1032            continue;
1033            }
1034            try {
1035            SignatureSpi JavaDoc spi = newInstance(s);
1036            init(spi, type, key, random);
1037            provider = s.getProvider();
1038            sigSpi = spi;
1039            firstService = null;
1040            serviceIterator = null;
1041            return;
1042            } catch (Exception JavaDoc e) {
1043            // NoSuchAlgorithmException from newInstance()
1044
// InvalidKeyException from init()
1045
// RuntimeException (ProviderException) from init()
1046
if (lastException == null) {
1047                lastException = e;
1048            }
1049            }
1050        }
1051        // no working provider found, fail
1052
if (lastException instanceof InvalidKeyException JavaDoc) {
1053            throw (InvalidKeyException JavaDoc)lastException;
1054        }
1055        if (lastException instanceof RuntimeException JavaDoc) {
1056            throw (RuntimeException JavaDoc)lastException;
1057        }
1058        String JavaDoc k = (key != null) ? key.getClass().getName() : "(null)";
1059        throw new InvalidKeyException JavaDoc
1060            ("No installed provider supports this key: "
1061            + k, lastException);
1062        }
1063    }
1064
1065    private final static int I_PUB = 1;
1066    private final static int I_PRIV = 2;
1067    private final static int I_PRIV_SR = 3;
1068    
1069    private void init(SignatureSpi JavaDoc spi, int type, Key JavaDoc key,
1070        SecureRandom JavaDoc random) throws InvalidKeyException JavaDoc {
1071        switch (type) {
1072        case I_PUB:
1073        spi.engineInitVerify((PublicKey JavaDoc)key);
1074        break;
1075        case I_PRIV:
1076        spi.engineInitSign((PrivateKey JavaDoc)key);
1077        break;
1078        case I_PRIV_SR:
1079        spi.engineInitSign((PrivateKey JavaDoc)key, random);
1080        break;
1081        default:
1082        throw new AssertionError JavaDoc("Internal error: " + type);
1083        }
1084    }
1085    
1086    protected void engineInitVerify(PublicKey JavaDoc publicKey)
1087            throws InvalidKeyException JavaDoc {
1088        if (sigSpi != null) {
1089        sigSpi.engineInitVerify(publicKey);
1090        } else {
1091        chooseProvider(I_PUB, publicKey, null);
1092        }
1093    }
1094    
1095    protected void engineInitSign(PrivateKey JavaDoc privateKey)
1096            throws InvalidKeyException JavaDoc {
1097        if (sigSpi != null) {
1098        sigSpi.engineInitSign(privateKey);
1099        } else {
1100        chooseProvider(I_PRIV, privateKey, null);
1101        }
1102    }
1103
1104        protected void engineInitSign(PrivateKey JavaDoc privateKey, SecureRandom JavaDoc sr)
1105                throws InvalidKeyException JavaDoc {
1106        if (sigSpi != null) {
1107        sigSpi.engineInitSign(privateKey, sr);
1108        } else {
1109        chooseProvider(I_PRIV_SR, privateKey, sr);
1110        }
1111        }
1112
1113    protected void engineUpdate(byte b) throws SignatureException JavaDoc {
1114        chooseFirstProvider();
1115        sigSpi.engineUpdate(b);
1116    }
1117
1118    protected void engineUpdate(byte[] b, int off, int len)
1119            throws SignatureException JavaDoc {
1120        chooseFirstProvider();
1121        sigSpi.engineUpdate(b, off, len);
1122    }
1123    
1124    protected void engineUpdate(ByteBuffer JavaDoc data) {
1125        chooseFirstProvider();
1126        sigSpi.engineUpdate(data);
1127    }
1128
1129    protected byte[] engineSign() throws SignatureException JavaDoc {
1130        chooseFirstProvider();
1131        return sigSpi.engineSign();
1132    }
1133
1134    protected int engineSign(byte[] outbuf, int offset, int len)
1135            throws SignatureException JavaDoc {
1136        chooseFirstProvider();
1137        return sigSpi.engineSign(outbuf, offset, len);
1138    }
1139
1140    protected boolean engineVerify(byte[] sigBytes)
1141            throws SignatureException JavaDoc {
1142        chooseFirstProvider();
1143        return sigSpi.engineVerify(sigBytes);
1144    }
1145
1146    protected boolean engineVerify(byte[] sigBytes, int offset, int length)
1147            throws SignatureException JavaDoc {
1148        chooseFirstProvider();
1149        return sigSpi.engineVerify(sigBytes, offset, length);
1150    }
1151
1152    protected void engineSetParameter(String JavaDoc param, Object JavaDoc value)
1153            throws InvalidParameterException JavaDoc {
1154        chooseFirstProvider();
1155        sigSpi.engineSetParameter(param, value);
1156    }
1157
1158    protected void engineSetParameter(AlgorithmParameterSpec JavaDoc params)
1159            throws InvalidAlgorithmParameterException JavaDoc {
1160        chooseFirstProvider();
1161        sigSpi.engineSetParameter(params);
1162    }
1163
1164    protected Object JavaDoc engineGetParameter(String JavaDoc param)
1165        throws InvalidParameterException JavaDoc {
1166        chooseFirstProvider();
1167        return sigSpi.engineGetParameter(param);
1168    }
1169
1170    protected AlgorithmParameters JavaDoc engineGetParameters() {
1171        chooseFirstProvider();
1172        return sigSpi.engineGetParameters();
1173    }
1174    }
1175
1176    // adapter for RSA/ECB/PKCS1Padding ciphers
1177
private static class CipherAdapter extends SignatureSpi JavaDoc {
1178    
1179    private final Cipher cipher;
1180    
1181    private ByteArrayOutputStream data;
1182    
1183    CipherAdapter(Cipher cipher) {
1184        this.cipher = cipher;
1185    }
1186    
1187    protected void engineInitVerify(PublicKey JavaDoc publicKey)
1188        throws InvalidKeyException JavaDoc {
1189        cipher.init(Cipher.DECRYPT_MODE, publicKey);
1190        if (data == null) {
1191        data = new ByteArrayOutputStream(128);
1192        } else {
1193        data.reset();
1194        }
1195    }
1196
1197    protected void engineInitSign(PrivateKey JavaDoc privateKey)
1198        throws InvalidKeyException JavaDoc {
1199        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
1200        data = null;
1201    }
1202    
1203    protected void engineInitSign(PrivateKey JavaDoc privateKey,
1204        SecureRandom JavaDoc random) throws InvalidKeyException JavaDoc {
1205        cipher.init(Cipher.ENCRYPT_MODE, privateKey, random);
1206        data = null;
1207    }
1208
1209    protected void engineUpdate(byte b) throws SignatureException JavaDoc {
1210        engineUpdate(new byte[] {b}, 0, 1);
1211    }
1212
1213    protected void engineUpdate(byte[] b, int off, int len)
1214        throws SignatureException JavaDoc {
1215        if (data != null) {
1216        data.write(b, off, len);
1217        return;
1218        }
1219        byte[] out = cipher.update(b, off, len);
1220        if ((out != null) && (out.length != 0)) {
1221        throw new SignatureException JavaDoc
1222            ("Cipher unexpectedly returned data");
1223        }
1224    }
1225    
1226    protected byte[] engineSign() throws SignatureException JavaDoc {
1227        try {
1228        return cipher.doFinal();
1229        } catch (IllegalBlockSizeException e) {
1230        throw new SignatureException JavaDoc("doFinal() failed", e);
1231        } catch (BadPaddingException e) {
1232        throw new SignatureException JavaDoc("doFinal() failed", e);
1233        }
1234    }
1235
1236    protected boolean engineVerify(byte[] sigBytes)
1237        throws SignatureException JavaDoc {
1238        try {
1239        byte[] out = cipher.doFinal(sigBytes);
1240        byte[] dataBytes = data.toByteArray();
1241        data.reset();
1242        return Arrays.equals(out, dataBytes);
1243        } catch (BadPaddingException e) {
1244        // e.g. wrong public key used
1245
// return false rather than throwing exception
1246
return false;
1247        } catch (IllegalBlockSizeException e) {
1248        throw new SignatureException JavaDoc("doFinal() failed", e);
1249        }
1250    }
1251
1252    protected void engineSetParameter(String JavaDoc param, Object JavaDoc value)
1253        throws InvalidParameterException JavaDoc {
1254        throw new InvalidParameterException JavaDoc("Parameters not supported");
1255    }
1256
1257    protected Object JavaDoc engineGetParameter(String JavaDoc param)
1258        throws InvalidParameterException JavaDoc {
1259        throw new InvalidParameterException JavaDoc("Parameters not supported");
1260    }
1261    
1262    }
1263
1264}
1265
1266
Popular Tags