001    /* Signature.java --- Signature Class
002       Copyright (C) 1999, 2002, 2003, 2004  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.security;
040    
041    import gnu.java.security.Engine;
042    
043    import java.lang.reflect.InvocationTargetException;
044    import java.nio.ByteBuffer;
045    import java.security.cert.Certificate;
046    import java.security.cert.X509Certificate;
047    import java.security.spec.AlgorithmParameterSpec;
048    
049    /**
050     * <code>Signature</code> is used to provide an interface to digital signature
051     * algorithms. Digital signatures provide authentication and data integrity of
052     * digital data.
053     * 
054     * <p>The GNU provider provides the NIST standard DSA which uses DSA and SHA-1.
055     * It can be specified by SHA/DSA, SHA-1/DSA or its OID. If the RSA signature
056     * algorithm is provided then it could be MD2/RSA. MD5/RSA, or SHA-1/RSA. The
057     * algorithm must be specified because there is no default.</p>
058     * 
059     * <p>Signature provides implementation-independent algorithms which are
060     * requested by the user through the <code>getInstance()<?code> methods. It can
061     * be requested by specifying just the algorithm name or by specifying both the
062     * algorithm name and provider name.</p>
063     * 
064     * <p>The three phases of using <code>Signature</code> are:</p>
065     * 
066     * <ol>
067     *   <li>Initializing:
068     *     <ul>
069     *       <li>It must be initialized with a private key for signing.</li>
070     *       <li>It must be initialized with a public key for verifying.</li>
071     *   </li>
072     *   
073     *   <li>Updating:
074     *   <p>Update the bytes for signing or verifying with calls to update.</p>
075     *   </li>
076     *   
077     *   <li>Signing or Verify the signature on the currently stored bytes by
078     *   calling sign or verify.</li>
079     * </ol>
080     *
081     * @author Mark Benvenuto  (ivymccough@worldnet.att.net)
082     */
083    public abstract class Signature extends SignatureSpi
084    {
085      /** Service name for signatures. */
086      private static final String SIGNATURE = "Signature";
087    
088      /**
089       * Possible state value which signifies that this instance has not yet been
090       * initialized.
091       */
092      protected static final int UNINITIALIZED = 0;
093    
094      /**
095       * Possible state value which signifies that this instance has been
096       * initialized for signing purposes.
097       */
098      protected static final int SIGN = 2;
099    
100      /**
101       * Possible state value which signifies that this instance has been
102       * initialized for verification purposes.
103       */
104      protected static final int VERIFY = 3;
105    
106      /** Current sate of this instance. */
107      protected int state = UNINITIALIZED;
108    
109      private String algorithm;
110      Provider provider;
111    
112      // Constructor.
113      // ------------------------------------------------------------------------
114    
115      /**
116       * Constructs a new <code>Signature</code> instance for a designated digital
117       * signature algorithm.
118       * 
119       * @param algorithm
120       *          the algorithm to use.
121       */
122      protected Signature(String algorithm)
123      {
124        this.algorithm = algorithm;
125        state = UNINITIALIZED;
126      }
127    
128      /**
129       * Returns an instance of <code>Signature</code> representing the specified
130       * signature.
131       * 
132       * @param algorithm the algorithm to use.
133       * @return a new instance repesenting the desired algorithm.
134       * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
135       *           provider.
136       * @throws IllegalArgumentException if <code>algorithm</code> is
137       *           <code>null</code> or is an empty string.
138       */
139      public static Signature getInstance(String algorithm)
140          throws NoSuchAlgorithmException
141      {
142        Provider[] p = Security.getProviders();
143        NoSuchAlgorithmException lastException = null;
144        for (int i = 0; i < p.length; i++)
145          try
146            {
147              return getInstance(algorithm, p[i]);
148            }
149          catch (NoSuchAlgorithmException x)
150            {
151              lastException = x;
152            }
153        if (lastException != null)
154          throw lastException;
155        throw new NoSuchAlgorithmException(algorithm);
156      }
157    
158      /**
159       * Returns an instance of <code>Signature</code> representing the specified
160       * signature from the named provider.
161       * 
162       * @param algorithm the algorithm to use.
163       * @param provider the name of the provider to use.
164       * @return a new instance repesenting the desired algorithm.
165       * @throws NoSuchProviderException if the named provider was not found.
166       * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
167       *           named provider.
168       * @throws IllegalArgumentException if either <code>algorithm</code> or
169       *           <code>provider</code> is <code>null</code> or empty.
170       */
171      public static Signature getInstance(String algorithm, String provider)
172          throws NoSuchAlgorithmException, NoSuchProviderException
173      {
174        if (provider == null)
175          throw new IllegalArgumentException("provider MUST NOT be null");
176        provider = provider.trim();
177        if (provider.length() == 0)
178          throw new IllegalArgumentException("provider MUST NOT be empty");
179        Provider p = Security.getProvider(provider);
180        if (p == null)
181          throw new NoSuchProviderException(provider);
182        return getInstance(algorithm, p);
183      }
184    
185      /**
186       * Returns an instance of <code>Signature</code> representing the specified
187       * signature from the specified {@link Provider}.
188       * 
189       * @param algorithm the algorithm to use.
190       * @param provider the {@link Provider} to use.
191       * @return a new instance repesenting the desired algorithm.
192       * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
193       *           {@link Provider}.
194       * @throws IllegalArgumentException if either <code>algorithm</code> or
195       *           <code>provider</code> is <code>null</code>, or if
196       *           <code>algorithm</code> is an empty string.
197       */
198      public static Signature getInstance(String algorithm, Provider provider)
199        throws NoSuchAlgorithmException
200      {
201        StringBuilder sb = new StringBuilder("Signature algorithm [")
202            .append(algorithm).append("] from provider[")
203            .append(provider).append("] ");
204        Object o;
205        try
206          {
207            o = Engine.getInstance(SIGNATURE, algorithm, provider);
208          }
209        catch (InvocationTargetException x)
210          {
211            Throwable cause = x.getCause();
212            if (cause instanceof NoSuchAlgorithmException)
213              throw (NoSuchAlgorithmException) cause;
214            if (cause == null)
215              cause = x;
216            sb.append("could not be created");
217            NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString());
218            y.initCause(cause);
219            throw y;
220          }
221        Signature result;
222        if (o instanceof SignatureSpi)
223          result = new DummySignature((SignatureSpi) o, algorithm);
224        else if (o instanceof Signature)
225          {
226            result = (Signature) o;
227            result.algorithm = algorithm;
228          }
229        else
230          {
231            sb.append("is of an unexpected Type: ").append(o.getClass().getName());
232            throw new NoSuchAlgorithmException(sb.toString());
233          }
234        result.provider = provider;
235        return result;
236      }
237    
238      /**
239       * Returns the {@link Provider} of this instance.
240       * 
241       * @return the {@link Provider} of this instance.
242       */
243      public final Provider getProvider()
244      {
245        return provider;
246      }
247    
248      /**
249       * Initializes this instance with the public key for verification purposes.
250       * 
251       * @param publicKey
252       *          the public key to verify with.
253       * @throws InvalidKeyException
254       *           if the key is invalid.
255       */
256      public final void initVerify(PublicKey publicKey) throws InvalidKeyException
257      {
258        state = VERIFY;
259        engineInitVerify(publicKey);
260      }
261    
262      /**
263       * Verify a signature with a designated {@link Certificate}. This is a FIPS
264       * 140-1 compatible method since it verifies a signature with a certificate.
265       * 
266       * <p>If the {@link Certificate} is an X.509 one, has a <i>KeyUsage</i>
267       * parameter and that parameter indicates this key is not to be used for
268       * signing then an exception is thrown.</p>
269       * 
270       * @param certificate
271       *          a {@link Certificate} containing a public key to verify with.
272       * @throws InvalidKeyException if the key is invalid.
273       */
274      public final void initVerify(Certificate certificate)
275        throws InvalidKeyException
276      {
277        state = VERIFY;
278        if (certificate.getType().equals("X509"))
279          {
280            X509Certificate cert = (X509Certificate) certificate;
281            boolean[]array = cert.getKeyUsage();
282            if (array != null && array[0] == false)
283              throw new InvalidKeyException(
284                  "KeyUsage of this Certificate indicates it cannot be used for digital signing");
285          }
286        this.initVerify(certificate.getPublicKey());
287      }
288    
289      /**
290       * Initializes this class with the private key for signing purposes.
291       * 
292       * @param privateKey
293       *          the private key to sign with.
294       * @throws InvalidKeyException
295       *           if the key is invalid.
296       */
297      public final void initSign(PrivateKey privateKey) throws InvalidKeyException
298      {
299        state = SIGN;
300        engineInitSign(privateKey);
301      }
302    
303      /**
304       * Initializes this class with the private key and source of randomness for
305       * signing purposes.
306       * 
307       * @param privateKey
308       *          the private key to sign with.
309       * @param random
310       *          the {@link SecureRandom} to use.
311       * @throws InvalidKeyException
312       *           if the key is invalid.
313       */
314      public final void initSign(PrivateKey privateKey, SecureRandom random)
315        throws InvalidKeyException
316      {
317        state = SIGN;
318        engineInitSign(privateKey, random);
319      }
320    
321      /**
322       * Returns the signature bytes of all the data fed to this instance. The
323       * format of the output depends on the underlying signature algorithm.
324       * 
325       * @return the signature bytes.
326       * @throws SignatureException
327       *           if the engine is not properly initialized.
328       */
329      public final byte[] sign() throws SignatureException
330      {
331        if (state == SIGN)
332          return engineSign();
333        else
334          throw new SignatureException();
335      }
336    
337      /**
338       * Generates signature bytes of all the data fed to this instance and stores
339       * it in the designated array. The format of the result depends on the
340       * underlying signature algorithm.
341       * 
342       * <p>After calling this method, the instance is reset to its initial state
343       * and can then be used to generate additional signatures.</p>
344       * 
345       * <p><b>IMPLEMENTATION NOTE:</b> Neither this method nor the GNU provider
346       * will return partial digests. If <code>len</code> is less than the
347       * signature length, this method will throw a {@link SignatureException}. If
348       * it is greater than or equal then it is ignored.</p>
349       * 
350       * @param outbuf
351       *          array of bytes of where to store the resulting signature bytes.
352       * @param offset
353       *          the offset to start at in the array.
354       * @param len
355       *          the number of the bytes to use in the array.
356       * @return the real number of bytes used.
357       * @throws SignatureException
358       *           if the engine is not properly initialized.
359       * @since 1.2
360       */
361      public final int sign(byte[] outbuf, int offset, int len)
362        throws SignatureException
363      {
364        if (state == SIGN)
365          return engineSign(outbuf, offset, len);
366        else
367          throw new SignatureException();
368      }
369    
370      /**
371       * Verifies a designated signature.
372       * 
373       * @param signature
374       *          the signature bytes to verify.
375       * @return <code>true</code> if verified, <code>false</code> otherwise.
376       * @throws SignatureException
377       *           if the engine is not properly initialized or the signature does
378       *           not check.
379       */
380      public final boolean verify(byte[]signature) throws SignatureException
381      {
382        if (state == VERIFY)
383          return engineVerify(signature);
384        else
385          throw new SignatureException();
386      }
387    
388      /**
389       * Verifies a designated signature.
390       * 
391       * @param signature
392       *          the signature bytes to verify.
393       * @param offset
394       *          the offset to start at in the array.
395       * @param length
396       *          the number of the bytes to use from the array.
397       * @return <code>true</code> if verified, <code>false</code> otherwise.
398       * @throws IllegalArgumentException
399       *           if the <code>signature</code> byte array is <code>null</code>,
400       *           or the <code>offset</code> or <code>length</code> is less
401       *           than <code>0</code>, or the sum of the <code>offset</code>
402       *           and <code>length</code> is greater than the length of the
403       *           <code>signature</code> byte array.
404       * @throws SignatureException
405       *           if the engine is not properly initialized or the signature does
406       *           not check.
407       */
408      public final boolean verify(byte[] signature, int offset, int length)
409        throws SignatureException
410      {
411        if (state != VERIFY)
412          throw new SignatureException("illegal state");
413    
414        if (signature == null)
415          throw new IllegalArgumentException("signature is null");
416        if (offset < 0)
417          throw new IllegalArgumentException("offset is less than 0");
418        if (length < 0)
419          throw new IllegalArgumentException("length is less than 0");
420        if (offset + length < signature.length)
421          throw new IllegalArgumentException("range is out of bounds");
422    
423        return engineVerify(signature, offset, length);
424      }
425    
426      /**
427       * Updates the data to be signed or verified with the specified byte.
428       * 
429       * @param b
430       *          the byte to update with.
431       * @throws SignatureException
432       *           if the engine is not properly initialized.
433       */
434      public final void update(byte b) throws SignatureException
435      {
436        if (state != UNINITIALIZED)
437          engineUpdate(b);
438        else
439          throw new SignatureException();
440      }
441    
442      /**
443       * Updates the data to be signed or verified with the specified bytes.
444       * 
445       * @param data
446       *          the array of bytes to use.
447       * @throws SignatureException
448       *           if the engine is not properly initialized.
449       */
450      public final void update(byte[]data) throws SignatureException
451      {
452        if (state != UNINITIALIZED)
453          engineUpdate(data, 0, data.length);
454        else
455          throw new SignatureException();
456      }
457    
458      /**
459       * Updates the data to be signed or verified with the specified bytes.
460       * 
461       * @param data
462       *          an array of bytes to use.
463       * @param off
464       *          the offset to start at in the array.
465       * @param len
466       *          the number of bytes to use from the array.
467       * @throws SignatureException
468       *           if the engine is not properly initialized.
469       */
470      public final void update(byte[]data, int off, int len)
471        throws SignatureException
472      {
473        if (state != UNINITIALIZED)
474          engineUpdate(data, off, len);
475        else
476          throw new SignatureException();
477      }
478      
479      /**
480       * Update this signature with the {@link java.nio.Buffer#remaining()}
481       * bytes of the input buffer.
482       * 
483       * @param input The input buffer.
484       * @throws SignatureException If this instance was not properly
485       *  initialized.
486       */
487      public final void update(ByteBuffer input) throws SignatureException
488      {
489        if (state != UNINITIALIZED)
490          engineUpdate(input);
491        else
492          throw new SignatureException("not initialized");
493      }
494    
495      /**
496       * Returns the name of the algorithm currently used. The names of algorithms
497       * are usually SHA/DSA or SHA/RSA.
498       * 
499       * @return name of algorithm.
500       */
501      public final String getAlgorithm()
502      {
503        return algorithm;
504      }
505    
506      /**
507       * Returns a rstring representation of this instance.
508       * 
509       * @return a rstring representation of this instance.
510       */
511      public String toString()
512      {
513        return (algorithm + " Signature");
514      }
515    
516      /**
517       * Sets the specified algorithm parameter to the specified value.
518       * 
519       * @param param
520       *          the parameter name.
521       * @param value
522       *          the parameter value.
523       * @throws InvalidParameterException
524       *           if the parameter is invalid, the parameter is already set and
525       *           can not be changed, a security exception occured, etc.
526       * @deprecated use the other setParameter
527       */
528      public final void setParameter(String param, Object value)
529        throws InvalidParameterException
530      {
531        engineSetParameter(param, value);
532      }
533    
534      /**
535       * Sets the signature engine with the specified {@link AlgorithmParameterSpec}.
536       * 
537       * <p>By default, and unless overriden by the concrete SPI, this method always
538       * throws an {@link UnsupportedOperationException}.</p>
539       * 
540       * @param params
541       *          the parameters to use for intializing this instance.
542       * @throws InvalidParameterException
543       *           if the parameter is invalid, the parameter is already set and
544       *           cannot be changed, a security exception occured, etc.
545       */
546      public final void setParameter(AlgorithmParameterSpec params)
547        throws InvalidAlgorithmParameterException
548      {
549        engineSetParameter(params);
550      }
551    
552      /**
553       * Return the parameters of the algorithm used in this instance as an
554       * {@link AlgorithmParameters}.
555       * 
556       * @return the parameters used with this instance, or <code>null</code> if
557       *         this instance does not use any parameters.
558       */
559      public final AlgorithmParameters getParameters()
560      {
561        return engineGetParameters();
562      }
563    
564      /**
565       * Returns the value for the specified algorithm parameter.
566       * 
567       * @param param
568       *          the parameter name.
569       * @return the parameter value.
570       * @throws InvalidParameterException
571       *           if the parameter is invalid.
572       * @deprecated use the other getParameter
573       */
574      public final Object getParameter(String param)
575        throws InvalidParameterException
576      {
577        return engineGetParameter(param);
578      }
579    
580      /**
581       * Returns a clone of this instance.
582       * 
583       * @return a clone of this instace.
584       * @throws CloneNotSupportedException
585       *           if the implementation does not support cloning.
586       */
587      public Object clone() throws CloneNotSupportedException
588      {
589        return super.clone();
590      }
591    }