GNU Classpath (0.95) | |
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.lang.reflect.InvocationTargetException; 44: import java.nio.ByteBuffer; 45: import java.security.cert.Certificate; 46: import java.security.cert.X509Certificate; 47: import java.security.spec.AlgorithmParameterSpec; 48: 49: /** 50: * <code>Signature</code> is used to provide an interface to digital signature 51: * algorithms. Digital signatures provide authentication and data integrity of 52: * digital data. 53: * 54: * <p>The GNU provider provides the NIST standard DSA which uses DSA and SHA-1. 55: * It can be specified by SHA/DSA, SHA-1/DSA or its OID. If the RSA signature 56: * algorithm is provided then it could be MD2/RSA. MD5/RSA, or SHA-1/RSA. The 57: * algorithm must be specified because there is no default.</p> 58: * 59: * <p>Signature provides implementation-independent algorithms which are 60: * requested by the user through the <code>getInstance()<?code> methods. It can 61: * be requested by specifying just the algorithm name or by specifying both the 62: * algorithm name and provider name.</p> 63: * 64: * <p>The three phases of using <code>Signature</code> are:</p> 65: * 66: * <ol> 67: * <li>Initializing: 68: * <ul> 69: * <li>It must be initialized with a private key for signing.</li> 70: * <li>It must be initialized with a public key for verifying.</li> 71: * </li> 72: * 73: * <li>Updating: 74: * <p>Update the bytes for signing or verifying with calls to update.</p> 75: * </li> 76: * 77: * <li>Signing or Verify the signature on the currently stored bytes by 78: * calling sign or verify.</li> 79: * </ol> 80: * 81: * @author Mark Benvenuto (ivymccough@worldnet.att.net) 82: */ 83: public abstract class Signature extends SignatureSpi 84: { 85: /** Service name for signatures. */ 86: private static final String SIGNATURE = "Signature"; 87: 88: /** 89: * Possible state value which signifies that this instance has not yet been 90: * initialized. 91: */ 92: protected static final int UNINITIALIZED = 0; 93: 94: /** 95: * Possible state value which signifies that this instance has been 96: * initialized for signing purposes. 97: */ 98: protected static final int SIGN = 2; 99: 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: }
GNU Classpath (0.95) |