Frames | No Frames |
1: /* Signature.java --- Signature Class 2: Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 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) 9: any later version. 10: 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. 15: 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 19: 02110-1301 USA. 20: 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 24: combination. 25: 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. */ 37: 38: 39: package java.security; 40: 41: import gnu.java.security.Engine; 42: 43: import java.security.cert.Certificate; 44: import java.security.cert.X509Certificate; 45: import java.security.spec.AlgorithmParameterSpec; 46: 47: /** 48: * <code>Signature</code> is used to provide an interface to digital signature 49: * algorithms. Digital signatures provide authentication and data integrity of 50: * digital data. 51: * 52: * <p>The GNU provider provides the NIST standard DSA which uses DSA and SHA-1. 53: * It can be specified by SHA/DSA, SHA-1/DSA or its OID. If the RSA signature 54: * algorithm is provided then it could be MD2/RSA. MD5/RSA, or SHA-1/RSA. The 55: * algorithm must be specified because there is no default.</p> 56: * 57: * <p>Signature provides implementation-independent algorithms which are 58: * requested by the user through the <code>getInstance()<?code> methods. It can 59: * be requested by specifying just the algorithm name or by specifying both the 60: * algorithm name and provider name.</p> 61: * 62: * <p>The three phases of using <code>Signature</code> are:</p> 63: * 64: * <ol> 65: * <li>Initializing: 66: * <ul> 67: * <li>It must be initialized with a private key for signing.</li> 68: * <li>It must be initialized with a public key for verifying.</li> 69: * </li> 70: * 71: * <li>Updating: 72: * <p>Update the bytes for signing or verifying with calls to update.</p> 73: * </li> 74: * 75: * <li>Signing or Verify the signature on the currently stored bytes by 76: * calling sign or verify.</li> 77: * </ol> 78: * 79: * @author Mark Benvenuto (ivymccough@worldnet.att.net) 80: */ 81: public abstract class Signature extends SignatureSpi 82: { 83: /** Service name for signatures. */ 84: private static final String SIGNATURE = "Signature"; 85: 86: /** 87: * Possible state value which signifies that this instance has not yet been 88: * initialized. 89: */ 90: protected static final int UNINITIALIZED = 0; 91: 92: /** 93: * Possible state value which signifies that this instance has been 94: * initialized for signing purposes. 95: */ 96: protected static final int SIGN = 2; 97: 98: /** 99: * Possible state value which signifies that this instance has been 100: * initialized for verification purposes. 101: */ 102: protected static final int VERIFY = 3; 103: 104: /** Current sate of this instance. */ 105: protected int state = UNINITIALIZED; 106: 107: private String algorithm; 108: Provider provider; 109: 110: // Constructor. 111: // ------------------------------------------------------------------------ 112: 113: /** 114: * Constructs a new <code>Signature</code> instance for a designated digital 115: * signature algorithm. 116: * 117: * @param algorithm 118: * the algorithm to use. 119: */ 120: protected Signature(String algorithm) 121: { 122: this.algorithm = algorithm; 123: state = UNINITIALIZED; 124: } 125: 126: /** 127: * Returns an instance of <code>Signature</code> representing the specified 128: * signature. 129: * 130: * @param algorithm 131: * the algorithm to use. 132: * @return a new instance repesenting the desired algorithm. 133: * @throws NoSuchAlgorithmException 134: * if the algorithm is not implemented by any provider. 135: */ 136: public static Signature getInstance(String algorithm) 137: throws NoSuchAlgorithmException 138: { 139: Provider[] p = Security.getProviders(); 140: for (int i = 0; i < p.length; i++) 141: { 142: try 143: { 144: return getInstance(algorithm, p[i]); 145: } 146: catch (NoSuchAlgorithmException e) 147: { 148: // Ignored. 149: } 150: } 151: 152: throw new NoSuchAlgorithmException(algorithm); 153: } 154: 155: /** 156: * Returns an instance of <code>Signature</code> representing the specified 157: * signature from the named provider. 158: * 159: * @param algorithm 160: * the algorithm to use. 161: * @param provider 162: * the name of the provider to use. 163: * @return a new instance repesenting the desired algorithm. 164: * @throws IllegalArgumentException if <code>provider</code> is 165: * <code>null</code> or is an empty string. 166: * @throws NoSuchProviderException 167: * if the named provider was not found. 168: * @throws NoSuchAlgorithmException 169: * if the algorithm is not implemented by the named provider. 170: */ 171: public static Signature getInstance(String algorithm, String provider) 172: throws NoSuchAlgorithmException, NoSuchProviderException 173: { 174: if (provider == null || provider.length() == 0) 175: throw new IllegalArgumentException("Illegal provider"); 176: 177: Provider p = Security.getProvider(provider); 178: if (p == null) 179: throw new NoSuchProviderException(provider); 180: 181: return getInstance(algorithm, p); 182: } 183: 184: /** 185: * Returns an instance of <code>Signature</code> representing the specified 186: * signature from the specified {@link Provider}. 187: * 188: * @param algorithm 189: * the algorithm to use. 190: * @param provider 191: * the {@link Provider} to use. 192: * @return a new instance repesenting the desired algorithm. 193: * @throws NoSuchAlgorithmException 194: * if the algorithm is not implemented by the {@link Provider}. 195: */ 196: public static Signature getInstance(String algorithm, Provider provider) 197: throws NoSuchAlgorithmException 198: { 199: if (provider == null) 200: throw new IllegalArgumentException("Illegal provider"); 201: 202: Signature result = null; 203: Object o = null; 204: try 205: { 206: o = Engine.getInstance(SIGNATURE, algorithm, provider); 207: } 208: catch (java.lang.reflect.InvocationTargetException ite) 209: { 210: throw new NoSuchAlgorithmException(algorithm); 211: } 212: 213: if (o instanceof SignatureSpi) 214: { 215: result = new DummySignature((SignatureSpi) o, algorithm); 216: } 217: else if (o instanceof Signature) 218: { 219: result = (Signature) o; 220: result.algorithm = algorithm; 221: } 222: else 223: { 224: throw new NoSuchAlgorithmException(algorithm); 225: } 226: result.provider = provider; 227: return result; 228: } 229: 230: /** 231: * Returns the {@link Provider} of this instance. 232: * 233: * @return the {@link Provider} of this instance. 234: */ 235: public final Provider getProvider() 236: { 237: return provider; 238: } 239: 240: /** 241: * Initializes this instance with the public key for verification purposes. 242: * 243: * @param publicKey 244: * the public key to verify with. 245: * @throws InvalidKeyException 246: * if the key is invalid. 247: */ 248: public final void initVerify(PublicKey publicKey) throws InvalidKeyException 249: { 250: state = VERIFY; 251: engineInitVerify(publicKey); 252: } 253: 254: /** 255: * Verify a signature with a designated {@link Certificate}. This is a FIPS 256: * 140-1 compatible method since it verifies a signature with a certificate. 257: * 258: * <p>If the {@link Certificate} is an X.509 one, has a <i>KeyUsage</i> 259: * parameter and that parameter indicates this key is not to be used for 260: * signing then an exception is thrown.</p> 261: * 262: * @param certificate 263: * a {@link Certificate} containing a public key to verify with. 264: * @throws InvalidKeyException if the key is invalid. 265: */ 266: public final void initVerify(Certificate certificate) 267: throws InvalidKeyException 268: { 269: state = VERIFY; 270: if (certificate.getType().equals("X509")) 271: { 272: X509Certificate cert = (X509Certificate) certificate; 273: boolean[]array = cert.getKeyUsage(); 274: if (array != null && array[0] == false) 275: throw new InvalidKeyException( 276: "KeyUsage of this Certificate indicates it cannot be used for digital signing"); 277: } 278: this.initVerify(certificate.getPublicKey()); 279: } 280: 281: /** 282: * Initializes this class with the private key for signing purposes. 283: * 284: * @param privateKey 285: * the private key to sign with. 286: * @throws InvalidKeyException 287: * if the key is invalid. 288: */ 289: public final void initSign(PrivateKey privateKey) throws InvalidKeyException 290: { 291: state = SIGN; 292: engineInitSign(privateKey); 293: } 294: 295: /** 296: * Initializes this class with the private key and source of randomness for 297: * signing purposes. 298: * 299: * @param privateKey 300: * the private key to sign with. 301: * @param random 302: * the {@link SecureRandom} to use. 303: * @throws InvalidKeyException 304: * if the key is invalid. 305: */ 306: public final void initSign(PrivateKey privateKey, SecureRandom random) 307: throws InvalidKeyException 308: { 309: state = SIGN; 310: engineInitSign(privateKey, random); 311: } 312: 313: /** 314: * Returns the signature bytes of all the data fed to this instance. The 315: * format of the output depends on the underlying signature algorithm. 316: * 317: * @return the signature bytes. 318: * @throws SignatureException 319: * if the engine is not properly initialized. 320: */ 321: public final byte[] sign() throws SignatureException 322: { 323: if (state == SIGN) 324: return engineSign(); 325: else 326: throw new SignatureException(); 327: } 328: 329: /** 330: * Generates signature bytes of all the data fed to this instance and stores 331: * it in the designated array. The format of the result depends on the 332: * underlying signature algorithm. 333: * 334: * <p>After calling this method, the instance is reset to its initial state 335: * and can then be used to generate additional signatures.</p> 336: * 337: * <p><b>IMPLEMENTATION NOTE:</b> Neither this method nor the GNU provider 338: * will return partial digests. If <code>len</code> is less than the 339: * signature length, this method will throw a {@link SignatureException}. If 340: * it is greater than or equal then it is ignored.</p> 341: * 342: * @param outbuf 343: * array of bytes of where to store the resulting signature bytes. 344: * @param offset 345: * the offset to start at in the array. 346: * @param len 347: * the number of the bytes to use in the array. 348: * @return the real number of bytes used. 349: * @throws SignatureException 350: * if the engine is not properly initialized. 351: * @since 1.2 352: */ 353: public final int sign(byte[] outbuf, int offset, int len) 354: throws SignatureException 355: { 356: if (state == SIGN) 357: return engineSign(outbuf, offset, len); 358: else 359: throw new SignatureException(); 360: } 361: 362: /** 363: * Verifies a designated signature. 364: * 365: * @param signature 366: * the signature bytes to verify. 367: * @return <code>true</code> if verified, <code>false</code> otherwise. 368: * @throws SignatureException 369: * if the engine is not properly initialized or the signature does 370: * not check. 371: */ 372: public final boolean verify(byte[]signature) throws SignatureException 373: { 374: if (state == VERIFY) 375: return engineVerify(signature); 376: else 377: throw new SignatureException(); 378: } 379: 380: /** 381: * Verifies a designated signature. 382: * 383: * @param signature 384: * the signature bytes to verify. 385: * @param offset 386: * the offset to start at in the array. 387: * @param length 388: * the number of the bytes to use from the array. 389: * @return <code>true</code> if verified, <code>false</code> otherwise. 390: * @throws IllegalArgumentException 391: * if the <code>signature</code> byte array is <code>null</code>, 392: * or the <code>offset</code> or <code>length</code> is less 393: * than <code>0</code>, or the sum of the <code>offset</code> 394: * and <code>length</code> is greater than the length of the 395: * <code>signature</code> byte array. 396: * @throws SignatureException 397: * if the engine is not properly initialized or the signature does 398: * not check. 399: */ 400: public final boolean verify(byte[] signature, int offset, int length) 401: throws SignatureException 402: { 403: if (state != VERIFY) 404: throw new SignatureException("illegal state"); 405: 406: if (signature == null) 407: throw new IllegalArgumentException("signature is null"); 408: if (offset < 0) 409: throw new IllegalArgumentException("offset is less than 0"); 410: if (length < 0) 411: throw new IllegalArgumentException("length is less than 0"); 412: if (offset + length < signature.length) 413: throw new IllegalArgumentException("range is out of bounds"); 414: 415: return engineVerify(signature, offset, length); 416: } 417: 418: /** 419: * Updates the data to be signed or verified with the specified byte. 420: * 421: * @param b 422: * the byte to update with. 423: * @throws SignatureException 424: * if the engine is not properly initialized. 425: */ 426: public final void update(byte b) throws SignatureException 427: { 428: if (state != UNINITIALIZED) 429: engineUpdate(b); 430: else 431: throw new SignatureException(); 432: } 433: 434: /** 435: * Updates the data to be signed or verified with the specified bytes. 436: * 437: * @param data 438: * the array of bytes to use. 439: * @throws SignatureException 440: * if the engine is not properly initialized. 441: */ 442: public final void update(byte[]data) throws SignatureException 443: { 444: if (state != UNINITIALIZED) 445: engineUpdate(data, 0, data.length); 446: else 447: throw new SignatureException(); 448: } 449: 450: /** 451: * Updates the data to be signed or verified with the specified bytes. 452: * 453: * @param data 454: * an array of bytes to use. 455: * @param off 456: * the offset to start at in the array. 457: * @param len 458: * the number of bytes to use from the array. 459: * @throws SignatureException 460: * if the engine is not properly initialized. 461: */ 462: public final void update(byte[]data, int off, int len) 463: throws SignatureException 464: { 465: if (state != UNINITIALIZED) 466: engineUpdate(data, off, len); 467: else 468: throw new SignatureException(); 469: } 470: 471: /** 472: * Returns the name of the algorithm currently used. The names of algorithms 473: * are usually SHA/DSA or SHA/RSA. 474: * 475: * @return name of algorithm. 476: */ 477: public final String getAlgorithm() 478: { 479: return algorithm; 480: } 481: 482: /** 483: * Returns a rstring representation of this instance. 484: * 485: * @return a rstring representation of this instance. 486: */ 487: public String toString() 488: { 489: return (algorithm + " Signature"); 490: } 491: 492: /** 493: * Sets the specified algorithm parameter to the specified value. 494: * 495: * @param param 496: * the parameter name. 497: * @param value 498: * the parameter value. 499: * @throws InvalidParameterException 500: * if the parameter is invalid, the parameter is already set and 501: * can not be changed, a security exception occured, etc. 502: * @deprecated use the other setParameter 503: */ 504: public final void setParameter(String param, Object value) 505: throws InvalidParameterException 506: { 507: engineSetParameter(param, value); 508: } 509: 510: /** 511: * Sets the signature engine with the specified {@link AlgorithmParameterSpec}. 512: * 513: * <p>By default, and unless overriden by the concrete SPI, this method always 514: * throws an {@link UnsupportedOperationException}.</p> 515: * 516: * @param params 517: * the parameters to use for intializing this instance. 518: * @throws InvalidParameterException 519: * if the parameter is invalid, the parameter is already set and 520: * cannot be changed, a security exception occured, etc. 521: */ 522: public final void setParameter(AlgorithmParameterSpec params) 523: throws InvalidAlgorithmParameterException 524: { 525: engineSetParameter(params); 526: } 527: 528: /** 529: * Return the parameters of the algorithm used in this instance as an 530: * {@link AlgorithmParameters}. 531: * 532: * @return the parameters used with this instance, or <code>null</code> if 533: * this instance does not use any parameters. 534: */ 535: public final AlgorithmParameters getParameters() 536: { 537: return engineGetParameters(); 538: } 539: 540: /** 541: * Returns the value for the specified algorithm parameter. 542: * 543: * @param param 544: * the parameter name. 545: * @return the parameter value. 546: * @throws InvalidParameterException 547: * if the parameter is invalid. 548: * @deprecated use the other getParameter 549: */ 550: public final Object getParameter(String param) 551: throws InvalidParameterException 552: { 553: return engineGetParameter(param); 554: } 555: 556: /** 557: * Returns a clone of this instance. 558: * 559: * @return a clone of this instace. 560: * @throws CloneNotSupportedException 561: * if the implementation does not support cloning. 562: */ 563: public Object clone() throws CloneNotSupportedException 564: { 565: return super.clone(); 566: } 567: }