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