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