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 }