1 /* Signature.java --- Signature Class
2 Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java
.security
;
41 import gnu
.java
.lang
.CPStringBuilder
;
43 import gnu
.java
.security
.Engine
;
45 import java
.lang
.reflect
.InvocationTargetException
;
46 import java
.nio
.ByteBuffer
;
47 import java
.security
.cert
.Certificate
;
48 import java
.security
.cert
.X509Certificate
;
49 import java
.security
.spec
.AlgorithmParameterSpec
;
52 * <code>Signature</code> is used to provide an interface to digital signature
53 * algorithms. Digital signatures provide authentication and data integrity of
56 * <p>The GNU provider provides the NIST standard DSA which uses DSA and SHA-1.
57 * It can be specified by SHA/DSA, SHA-1/DSA or its OID. If the RSA signature
58 * algorithm is provided then it could be MD2/RSA. MD5/RSA, or SHA-1/RSA. The
59 * algorithm must be specified because there is no default.</p>
61 * <p>Signature provides implementation-independent algorithms which are
62 * requested by the user through the <code>getInstance()<?code> methods. It can
63 * be requested by specifying just the algorithm name or by specifying both the
64 * algorithm name and provider name.</p>
66 * <p>The three phases of using <code>Signature</code> are:</p>
71 * <li>It must be initialized with a private key for signing.</li>
72 * <li>It must be initialized with a public key for verifying.</li>
76 * <p>Update the bytes for signing or verifying with calls to update.</p>
79 * <li>Signing or Verify the signature on the currently stored bytes by
80 * calling sign or verify.</li>
83 * @author Mark Benvenuto (ivymccough@worldnet.att.net)
85 public abstract class Signature
extends SignatureSpi
87 /** Service name for signatures. */
88 private static final String SIGNATURE
= "Signature";
91 * Possible state value which signifies that this instance has not yet been
94 protected static final int UNINITIALIZED
= 0;
97 * Possible state value which signifies that this instance has been
98 * initialized for signing purposes.
100 protected static final int SIGN
= 2;
103 * Possible state value which signifies that this instance has been
104 * initialized for verification purposes.
106 protected static final int VERIFY
= 3;
108 /** Current sate of this instance. */
109 protected int state
= UNINITIALIZED
;
111 private String algorithm
;
115 // ------------------------------------------------------------------------
118 * Constructs a new <code>Signature</code> instance for a designated digital
119 * signature algorithm.
122 * the algorithm to use.
124 protected Signature(String algorithm
)
126 this.algorithm
= algorithm
;
127 state
= UNINITIALIZED
;
131 * Returns an instance of <code>Signature</code> representing the specified
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
138 * @throws IllegalArgumentException if <code>algorithm</code> is
139 * <code>null</code> or is an empty string.
141 public static Signature
getInstance(String algorithm
)
142 throws NoSuchAlgorithmException
144 Provider
[] p
= Security
.getProviders();
145 NoSuchAlgorithmException lastException
= null;
146 for (int i
= 0; i
< p
.length
; i
++)
149 return getInstance(algorithm
, p
[i
]);
151 catch (NoSuchAlgorithmException x
)
155 if (lastException
!= null)
157 throw new NoSuchAlgorithmException(algorithm
);
161 * Returns an instance of <code>Signature</code> representing the specified
162 * signature from the named provider.
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
170 * @throws IllegalArgumentException if either <code>algorithm</code> or
171 * <code>provider</code> is <code>null</code> or empty.
173 public static Signature
getInstance(String algorithm
, String provider
)
174 throws NoSuchAlgorithmException
, NoSuchProviderException
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
);
183 throw new NoSuchProviderException(provider
);
184 return getInstance(algorithm
, p
);
188 * Returns an instance of <code>Signature</code> representing the specified
189 * signature from the specified {@link Provider}.
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
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.
200 public static Signature
getInstance(String algorithm
, Provider provider
)
201 throws NoSuchAlgorithmException
203 CPStringBuilder sb
= new CPStringBuilder("Signature algorithm [")
204 .append(algorithm
).append("] from provider[")
205 .append(provider
).append("] ");
209 o
= Engine
.getInstance(SIGNATURE
, algorithm
, provider
);
211 catch (InvocationTargetException x
)
213 Throwable cause
= x
.getCause();
214 if (cause
instanceof NoSuchAlgorithmException
)
215 throw (NoSuchAlgorithmException
) cause
;
218 sb
.append("could not be created");
219 NoSuchAlgorithmException y
= new NoSuchAlgorithmException(sb
.toString());
224 if (o
instanceof SignatureSpi
)
225 result
= new DummySignature((SignatureSpi
) o
, algorithm
);
226 else if (o
instanceof Signature
)
228 result
= (Signature
) o
;
229 result
.algorithm
= algorithm
;
233 sb
.append("is of an unexpected Type: ").append(o
.getClass().getName());
234 throw new NoSuchAlgorithmException(sb
.toString());
236 result
.provider
= provider
;
241 * Returns the {@link Provider} of this instance.
243 * @return the {@link Provider} of this instance.
245 public final Provider
getProvider()
251 * Initializes this instance with the public key for verification purposes.
254 * the public key to verify with.
255 * @throws InvalidKeyException
256 * if the key is invalid.
258 public final void initVerify(PublicKey publicKey
) throws InvalidKeyException
261 engineInitVerify(publicKey
);
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.
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>
273 * a {@link Certificate} containing a public key to verify with.
274 * @throws InvalidKeyException if the key is invalid.
276 public final void initVerify(Certificate certificate
)
277 throws InvalidKeyException
280 if (certificate
.getType().equals("X509"))
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");
288 this.initVerify(certificate
.getPublicKey());
292 * Initializes this class with the private key for signing purposes.
295 * the private key to sign with.
296 * @throws InvalidKeyException
297 * if the key is invalid.
299 public final void initSign(PrivateKey privateKey
) throws InvalidKeyException
302 engineInitSign(privateKey
);
306 * Initializes this class with the private key and source of randomness for
310 * the private key to sign with.
312 * the {@link SecureRandom} to use.
313 * @throws InvalidKeyException
314 * if the key is invalid.
316 public final void initSign(PrivateKey privateKey
, SecureRandom random
)
317 throws InvalidKeyException
320 engineInitSign(privateKey
, random
);
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.
327 * @return the signature bytes.
328 * @throws SignatureException
329 * if the engine is not properly initialized.
331 public final byte[] sign() throws SignatureException
336 throw new SignatureException();
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.
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>
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>
353 * array of bytes of where to store the resulting signature bytes.
355 * the offset to start at in the array.
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.
363 public final int sign(byte[] outbuf
, int offset
, int len
)
364 throws SignatureException
367 return engineSign(outbuf
, offset
, len
);
369 throw new SignatureException();
373 * Verifies a designated 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
382 public final boolean verify(byte[]signature
) throws SignatureException
385 return engineVerify(signature
);
387 throw new SignatureException();
391 * Verifies a designated signature.
394 * the signature bytes to verify.
396 * the offset to start at in the array.
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
410 public final boolean verify(byte[] signature
, int offset
, int length
)
411 throws SignatureException
414 throw new SignatureException("illegal state");
416 if (signature
== null)
417 throw new IllegalArgumentException("signature is null");
419 throw new IllegalArgumentException("offset is less than 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");
425 return engineVerify(signature
, offset
, length
);
429 * Updates the data to be signed or verified with the specified byte.
432 * the byte to update with.
433 * @throws SignatureException
434 * if the engine is not properly initialized.
436 public final void update(byte b
) throws SignatureException
438 if (state
!= UNINITIALIZED
)
441 throw new SignatureException();
445 * Updates the data to be signed or verified with the specified bytes.
448 * the array of bytes to use.
449 * @throws SignatureException
450 * if the engine is not properly initialized.
452 public final void update(byte[]data
) throws SignatureException
454 if (state
!= UNINITIALIZED
)
455 engineUpdate(data
, 0, data
.length
);
457 throw new SignatureException();
461 * Updates the data to be signed or verified with the specified bytes.
464 * an array of bytes to use.
466 * the offset to start at in the array.
468 * the number of bytes to use from the array.
469 * @throws SignatureException
470 * if the engine is not properly initialized.
472 public final void update(byte[]data
, int off
, int len
)
473 throws SignatureException
475 if (state
!= UNINITIALIZED
)
476 engineUpdate(data
, off
, len
);
478 throw new SignatureException();
482 * Update this signature with the {@link java.nio.Buffer#remaining()}
483 * bytes of the input buffer.
485 * @param input The input buffer.
486 * @throws SignatureException If this instance was not properly
489 public final void update(ByteBuffer input
) throws SignatureException
491 if (state
!= UNINITIALIZED
)
494 throw new SignatureException("not initialized");
498 * Returns the name of the algorithm currently used. The names of algorithms
499 * are usually SHA/DSA or SHA/RSA.
501 * @return name of algorithm.
503 public final String
getAlgorithm()
509 * Returns a rstring representation of this instance.
511 * @return a rstring representation of this instance.
513 public String
toString()
515 return (algorithm
+ " Signature");
519 * Sets the specified algorithm parameter to the specified value.
522 * the parameter name.
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
530 public final void setParameter(String param
, Object value
)
531 throws InvalidParameterException
533 engineSetParameter(param
, value
);
537 * Sets the signature engine with the specified {@link AlgorithmParameterSpec}.
539 * <p>By default, and unless overriden by the concrete SPI, this method always
540 * throws an {@link UnsupportedOperationException}.</p>
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.
548 public final void setParameter(AlgorithmParameterSpec params
)
549 throws InvalidAlgorithmParameterException
551 engineSetParameter(params
);
555 * Return the parameters of the algorithm used in this instance as an
556 * {@link AlgorithmParameters}.
558 * @return the parameters used with this instance, or <code>null</code> if
559 * this instance does not use any parameters.
561 public final AlgorithmParameters
getParameters()
563 return engineGetParameters();
567 * Returns the value for the specified algorithm parameter.
570 * the parameter name.
571 * @return the parameter value.
572 * @throws InvalidParameterException
573 * if the parameter is invalid.
574 * @deprecated use the other getParameter
576 public final Object
getParameter(String param
)
577 throws InvalidParameterException
579 return engineGetParameter(param
);
583 * Returns a clone of this instance.
585 * @return a clone of this instace.
586 * @throws CloneNotSupportedException
587 * if the implementation does not support cloning.
589 public Object
clone() throws CloneNotSupportedException
591 return super.clone();