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.lang.CPStringBuilder; 42: 43: import gnu.java.security.Engine; 44: 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; 50: 51: /** 52: * <code>Signature</code> is used to provide an interface to digital signature 53: * algorithms. Digital signatures provide authentication and data integrity of 54: * digital data. 55: * 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> 60: * 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> 65: * 66: * <p>The three phases of using <code>Signature</code> are:</p> 67: * 68: * <ol> 69: * <li>Initializing: 70: * <ul> 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> 73: * </li> 74: * 75: * <li>Updating: 76: * <p>Update the bytes for signing or verifying with calls to update.</p> 77: * </li> 78: * 79: * <li>Signing or Verify the signature on the currently stored bytes by 80: * calling sign or verify.</li> 81: * </ol> 82: * 83: * @author Mark Benvenuto (ivymccough@worldnet.att.net) 84: */ 85: public abstract class Signature extends SignatureSpi 86: { 87: /** Service name for signatures. */ 88: private static final String SIGNATURE = "Signature"; 89: 90: /** 91: * Possible state value which signifies that this instance has not yet been 92: * initialized. 93: */ 94: protected static final int UNINITIALIZED = 0; 95: 96: /** 97: * Possible state value which signifies that this instance has been 98: * initialized for signing purposes. 99: */ 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: }