GNU Classpath (0.95) | |
Frames | No Frames |
1: /* MessageDigest.java --- The message digest interface. 2: Copyright (C) 1999, 2002, 2003, 2006 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: package java.security; 39: 40: import gnu.java.security.Engine; 41: import java.nio.ByteBuffer; 42: 43: import java.lang.reflect.InvocationTargetException; 44: 45: /** 46: * Message digests are secure one-way hash functions that take arbitrary-sized 47: * data and output a fixed-length hash value. 48: * 49: * @see MessageDigestSpi 50: * @since JDK 1.1 51: */ 52: public abstract class MessageDigest extends MessageDigestSpi 53: { 54: /** The service name for message digests. */ 55: private static final String MESSAGE_DIGEST = "MessageDigest"; 56: 57: private String algorithm; 58: Provider provider; 59: private byte[] lastDigest; 60: 61: /** 62: * Constructs a new instance of <code>MessageDigest</code> representing the 63: * specified algorithm. 64: * 65: * @param algorithm 66: * the name of the digest algorithm to use. 67: */ 68: protected MessageDigest(String algorithm) 69: { 70: this.algorithm = algorithm; 71: provider = null; 72: } 73: 74: /** 75: * Returns a new instance of <code>MessageDigest</code> representing the 76: * specified algorithm. 77: * 78: * @param algorithm the name of the digest algorithm to use. 79: * @return a new instance representing the desired algorithm. 80: * @throws NoSuchAlgorithmException if the algorithm is not implemented by any 81: * provider. 82: * @throws IllegalArgumentException if <code>algorithm</code> is 83: * <code>null</code> or is an empty string. 84: */ 85: public static MessageDigest getInstance(String algorithm) 86: throws NoSuchAlgorithmException 87: { 88: Provider[] p = Security.getProviders(); 89: NoSuchAlgorithmException lastException = null; 90: for (int i = 0; i < p.length; i++) 91: try 92: { 93: return getInstance(algorithm, p[i]); 94: } 95: catch (NoSuchAlgorithmException x) 96: { 97: lastException = x; 98: } 99: if (lastException != null) 100: throw lastException; 101: throw new NoSuchAlgorithmException(algorithm); 102: } 103: 104: /** 105: * Returns a new instance of <code>MessageDigest</code> representing the 106: * specified algorithm from a named provider. 107: * 108: * @param algorithm the name of the digest algorithm to use. 109: * @param provider the name of the provider to use. 110: * @return a new instance representing the desired algorithm. 111: * @throws NoSuchAlgorithmException if the algorithm is not implemented by the 112: * named provider. 113: * @throws NoSuchProviderException if the named provider was not found. 114: * @throws IllegalArgumentException if either <code>algorithm</code> or 115: * <code>provider</code> is <code>null</code> or empty. 116: */ 117: public static MessageDigest getInstance(String algorithm, String provider) 118: throws NoSuchAlgorithmException, NoSuchProviderException 119: { 120: if (provider == null) 121: throw new IllegalArgumentException("provider MUST NOT be null"); 122: provider = provider.trim(); 123: if (provider.length() == 0) 124: throw new IllegalArgumentException("provider MUST NOT be empty"); 125: Provider p = Security.getProvider(provider); 126: if (p == null) 127: throw new NoSuchProviderException(provider); 128: return getInstance(algorithm, p); 129: } 130: 131: /** 132: * Returns a new instance of <code>MessageDigest</code> representing the 133: * specified algorithm from a designated {@link Provider}. 134: * 135: * @param algorithm the name of the digest algorithm to use. 136: * @param provider the {@link Provider} to use. 137: * @return a new instance representing the desired algorithm. 138: * @throws NoSuchAlgorithmException if the algorithm is not implemented by 139: * {@link Provider}. 140: * @throws IllegalArgumentException if either <code>algorithm</code> or 141: * <code>provider</code> is <code>null</code>, or if 142: * <code>algorithm</code> is an empty string. 143: * @since 1.4 144: * @see Provider 145: */ 146: public static MessageDigest getInstance(String algorithm, Provider provider) 147: throws NoSuchAlgorithmException 148: { 149: StringBuilder sb = new StringBuilder("MessageDigest for algorithm [") 150: .append(algorithm).append("] from provider[") 151: .append(provider).append("] "); 152: Object o; 153: try 154: { 155: o = Engine.getInstance(MESSAGE_DIGEST, algorithm, provider); 156: } 157: catch (InvocationTargetException x) 158: { 159: Throwable cause = x.getCause(); 160: if (cause instanceof NoSuchAlgorithmException) 161: throw (NoSuchAlgorithmException) cause; 162: if (cause == null) 163: cause = x; 164: sb.append("could not be created"); 165: NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString()); 166: y.initCause(cause); 167: throw y; 168: } 169: MessageDigest result; 170: if (o instanceof MessageDigestSpi) 171: result = new DummyMessageDigest((MessageDigestSpi) o, algorithm); 172: else if (o instanceof MessageDigest) 173: { 174: result = (MessageDigest) o; 175: result.algorithm = algorithm; 176: } 177: else 178: { 179: sb.append("is of an unexpected Type: ").append(o.getClass().getName()); 180: throw new NoSuchAlgorithmException(sb.toString()); 181: } 182: result.provider = provider; 183: return result; 184: } 185: 186: /** 187: * Returns the {@link Provider} of this instance. 188: * 189: * @return the {@link Provider} of this instance. 190: */ 191: public final Provider getProvider() 192: { 193: return provider; 194: } 195: 196: /** 197: * Updates the digest with the byte. 198: * 199: * @param input byte to update the digest with. 200: */ 201: public void update(byte input) 202: { 203: engineUpdate(input); 204: } 205: 206: /** 207: * Updates the digest with the bytes from the array starting from the 208: * specified offset and using the specified length of bytes. 209: * 210: * @param input 211: * bytes to update the digest with. 212: * @param offset 213: * the offset to start at. 214: * @param len 215: * length of the data to update with. 216: */ 217: public void update(byte[] input, int offset, int len) 218: { 219: engineUpdate(input, offset, len); 220: } 221: 222: /** 223: * Updates the digest with the bytes of an array. 224: * 225: * @param input bytes to update the digest with. 226: */ 227: public void update(byte[] input) 228: { 229: engineUpdate(input, 0, input.length); 230: } 231: 232: /** 233: * Updates the digest with the remaining bytes of a buffer. 234: * 235: * @param input The input byte buffer. 236: * @since 1.5 237: */ 238: public void update (ByteBuffer input) 239: { 240: engineUpdate (input); 241: } 242: 243: /** 244: * Computes the final digest of the stored data. 245: * 246: * @return a byte array representing the message digest. 247: */ 248: public byte[] digest() 249: { 250: return lastDigest = engineDigest(); 251: } 252: 253: /** 254: * Computes the final digest of the stored bytes and returns the result. 255: * 256: * @param buf 257: * an array of bytes to store the result in. 258: * @param offset 259: * an offset to start storing the result at. 260: * @param len 261: * the length of the buffer. 262: * @return Returns the length of the buffer. 263: */ 264: public int digest(byte[] buf, int offset, int len) throws DigestException 265: { 266: return engineDigest(buf, offset, len); 267: } 268: 269: /** 270: * Computes a final update using the input array of bytes, then computes a 271: * final digest and returns it. It calls {@link #update(byte[])} and then 272: * {@link #digest(byte[])}. 273: * 274: * @param input 275: * an array of bytes to perform final update with. 276: * @return a byte array representing the message digest. 277: */ 278: public byte[] digest(byte[] input) 279: { 280: update(input); 281: return digest(); 282: } 283: 284: /** 285: * Returns a string representation of this instance. 286: * 287: * @return a string representation of this instance. 288: */ 289: public String toString() 290: { 291: return (getClass()).getName() + " Message Digest <" + digestToString() + ">"; 292: } 293: 294: /** 295: * Does a simple byte comparison of the two digests. 296: * 297: * @param digesta 298: * first digest to compare. 299: * @param digestb 300: * second digest to compare. 301: * @return <code>true</code> if both are equal, <code>false</code> 302: * otherwise. 303: */ 304: public static boolean isEqual(byte[] digesta, byte[] digestb) 305: { 306: if (digesta.length != digestb.length) 307: return false; 308: 309: for (int i = digesta.length - 1; i >= 0; --i) 310: if (digesta[i] != digestb[i]) 311: return false; 312: 313: return true; 314: } 315: 316: /** Resets this instance. */ 317: public void reset() 318: { 319: engineReset(); 320: } 321: 322: /** 323: * Returns the name of message digest algorithm. 324: * 325: * @return the name of message digest algorithm. 326: */ 327: public final String getAlgorithm() 328: { 329: return algorithm; 330: } 331: 332: /** 333: * Returns the length of the message digest. The default is zero which means 334: * that the concrete implementation does not implement this method. 335: * 336: * @return length of the message digest. 337: * @since 1.2 338: */ 339: public final int getDigestLength() 340: { 341: return engineGetDigestLength(); 342: } 343: 344: /** 345: * Returns a clone of this instance if cloning is supported. If it does not 346: * then a {@link CloneNotSupportedException} is thrown. Cloning depends on 347: * whether the subclass {@link MessageDigestSpi} implements {@link Cloneable} 348: * which contains the actual implementation of the appropriate algorithm. 349: * 350: * @return a clone of this instance. 351: * @throws CloneNotSupportedException 352: * the implementation does not support cloning. 353: */ 354: public Object clone() throws CloneNotSupportedException 355: { 356: return super.clone(); 357: } 358: 359: private String digestToString() 360: { 361: byte[] digest = lastDigest; 362: 363: if (digest == null) 364: return "incomplete"; 365: 366: StringBuffer buf = new StringBuffer(); 367: int len = digest.length; 368: for (int i = 0; i < len; ++i) 369: { 370: byte b = digest[i]; 371: byte high = (byte) ((b & 0xff) >>> 4); 372: byte low = (byte) (b & 0xf); 373: 374: buf.append(high > 9 ? ('a' - 10) + high : '0' + high); 375: buf.append(low > 9 ? ('a' - 10) + low : '0' + low); 376: } 377: 378: return buf.toString(); 379: } 380: }
GNU Classpath (0.95) |