Source for java.security.MessageDigest

   1: /* MessageDigest.java --- The message digest interface.
   2:    Copyright (C) 1999, 2002, 2003 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:  * <p>This <code>MessageDigest</code> class provides applications the
  44:  * functionality of a message digest algorithm, such as <i>MD5</i> or <i>SHA</i>.
  45:  * Message digests are secure one-way hash functions that take arbitrary-sized
  46:  * data and output a fixed-length hash value.</p>
  47:  *
  48:  * <p>A <code>MessageDigest</code> object starts out initialized. The data is
  49:  * processed through it using the <code>update()</code> methods. At any point
  50:  * <code>reset()</code> can be called to reset the digest. Once all the data to
  51:  * be updated has been updated, one of the <code>digest()</code> methods should
  52:  * be called to complete the hash computation.</p>
  53:  *
  54:  * <p>The <code>digest()</code> method can be called <b>once</b> for a given
  55:  * number of updates. After <code>digest()</code> has been called, the
  56:  * <code>MessageDigest</code> object is <b>reset</b> to its initialized state.
  57:  * </p>
  58:  *
  59:  * <p>Implementations are free to implement the {@link Cloneable} interface.
  60:  * Client applications can test cloneability by attempting cloning and catching
  61:  * the {@link CloneNotSupportedException}:
  62:  *
  63:  * <pre>
  64:  *    MessageDigest md = MessageDigest.getInstance("SHA");
  65:  *    try
  66:  *      {
  67:  *        md.update(toChapter1);
  68:  *        MessageDigest tc1 = md.clone();
  69:  *        byte[] toChapter1Digest = tc1.digest();
  70:  *        md.update(toChapter2);
  71:  *        // ...
  72:  *      }
  73:  *    catch (CloneNotSupportedException x)
  74:  *      {
  75:  *        throw new DigestException("couldn't make digest of partial content");
  76:  *      }
  77:  * </pre>
  78:  *
  79:  * <p>Note that if a given implementation is not cloneable, it is still possible
  80:  * to compute intermediate digests by instantiating several instances, if the
  81:  * number of digests is known in advance.</p>
  82:  *
  83:  * <p>Note that this class is abstract and extends from {@link MessageDigestSpi}
  84:  * for historical reasons. Application developers should only take notice of the
  85:  * methods defined in this <code>MessageDigest</code> class; all the methods in
  86:  * the superclass are intended for cryptographic service providers who wish to
  87:  * supply their own implementations of message digest algorithms.</p>
  88:  *
  89:  * @see MessageDigestSpi
  90:  * @see Provider
  91:  * @since JDK 1.1
  92:  */
  93: public abstract class MessageDigest extends MessageDigestSpi
  94: {
  95:   /** The service name for message digests. */
  96:   private static final String MESSAGE_DIGEST = "MessageDigest";
  97: 
  98:   private String algorithm;
  99:   Provider provider;
 100:   private byte[] lastDigest;
 101: 
 102:   /**
 103:    * Creates a message digest with the specified algorithm name.
 104:    *
 105:    * @param algorithm the standard name of the digest algorithm.
 106:    * See Appendix A in the Java Cryptography Architecture API
 107:    * Specification &amp; Reference for information about standard
 108:    * algorithm names.
 109:    */
 110:   protected MessageDigest(String algorithm)
 111:   {
 112:     this.algorithm = algorithm;
 113:     provider = null;
 114:   }
 115: 
 116:   /**
 117:    * Generates a <code>MessageDigest</code> object that implements the specified
 118:    * digest algorithm. If the default provider package provides an
 119:    * implementation of the requested digest algorithm, an instance of
 120:    * <code>MessageDigest</code> containing that implementation is returned. If
 121:    * the algorithm is not available in the default package, other packages are
 122:    * searched.
 123:    *
 124:    * @param algorithm the name of the algorithm requested. See Appendix A in the
 125:    * Java Cryptography Architecture API Specification &amp; Reference for
 126:    * information about standard algorithm names.
 127:    * @return a Message Digest object implementing the specified algorithm.
 128:    * @throws NoSuchAlgorithmException if the algorithm is not available in the
 129:    * caller's environment.
 130:    */
 131:   public static MessageDigest getInstance(String algorithm)
 132:     throws NoSuchAlgorithmException
 133:   {
 134:     Provider[] p = Security.getProviders();
 135:     for (int i = 0; i < p.length; i++)
 136:       {
 137:         try
 138:           {
 139:             return getInstance(algorithm, p[i]);
 140:           }
 141:         catch (NoSuchAlgorithmException ignored)
 142:       {
 143:         // Ignore.
 144:       }
 145:       }
 146: 
 147:     throw new NoSuchAlgorithmException(algorithm);
 148:   }
 149: 
 150:   /**
 151:    * Generates a <code>MessageDigest</code> object implementing the specified
 152:    * algorithm, as supplied from the specified provider, if such an algorithm is
 153:    * available from the provider.
 154:    *
 155:    * @param algorithm the name of the algorithm requested. See Appendix A in the
 156:    * Java Cryptography Architecture API Specification &amp; Reference for
 157:    * information about standard algorithm names.
 158:    * @param provider the name of the provider.
 159:    * @return a Message Digest object implementing the specified algorithm.
 160:    * @throws NoSuchAlgorithmException if the algorithm is not available in the
 161:    * package supplied by the requested provider.
 162:    * @throws NoSuchProviderException if the provider is not available in the
 163:    * environment.
 164:    * @throws IllegalArgumentException if the provider name is null or empty.
 165:    * @see Provider
 166:    */
 167:   public static MessageDigest getInstance(String algorithm, String provider)
 168:     throws NoSuchAlgorithmException, NoSuchProviderException
 169:   {
 170:     if (provider == null || provider.length() == 0)
 171:       throw new IllegalArgumentException("Illegal provider");
 172: 
 173:     Provider p = Security.getProvider(provider);
 174:     if (p == null)
 175:       throw new NoSuchProviderException(provider);
 176: 
 177:     return getInstance(algorithm, p);
 178:   }
 179: 
 180:   /**
 181:    * Generates a <code>MessageDigest</code> object implementing the specified
 182:    * algorithm, as supplied from the specified provider, if such an algorithm
 183:    * is available from the provider. Note: the provider doesn't have to be
 184:    * registered.
 185:    *
 186:    * @param algorithm the name of the algorithm requested. See Appendix A in
 187:    * the Java Cryptography Architecture API Specification &amp; Reference for
 188:    * information about standard algorithm names.
 189:    * @param provider the provider.
 190:    * @return a Message Digest object implementing the specified algorithm.
 191:    * @throws NoSuchAlgorithmException if the <code>algorithm</code> is not
 192:    * available in the package supplied by the requested <code>provider</code>.
 193:    * @throws IllegalArgumentException if the <code>provider</code> is
 194:    * <code>null</code>.
 195:    * @since 1.4
 196:    * @see Provider
 197:    */
 198:   public static MessageDigest getInstance(String algorithm, Provider provider)
 199:     throws NoSuchAlgorithmException
 200:   {
 201:     if (provider == null)
 202:       throw new IllegalArgumentException("Illegal provider");
 203: 
 204:     MessageDigest result = null;
 205:     Object o = null;
 206:     try
 207:       {
 208:         o = Engine.getInstance(MESSAGE_DIGEST, algorithm, provider);
 209:       }
 210:     catch (java.lang.reflect.InvocationTargetException ite)
 211:       {
 212:         throw new NoSuchAlgorithmException(algorithm);
 213:       }
 214: 
 215:     if (o instanceof MessageDigestSpi)
 216:       {
 217:         result = new DummyMessageDigest((MessageDigestSpi) o, algorithm);
 218:       }
 219:     else if (o instanceof MessageDigest)
 220:       {
 221:         result = (MessageDigest) o;
 222:         result.algorithm = algorithm;
 223:       }
 224:     else
 225:       {
 226:         throw new NoSuchAlgorithmException(algorithm);
 227:       }
 228:     result.provider = provider;
 229:     return result;
 230:   }
 231: 
 232:   /**
 233:    * Returns the provider of this message digest object.
 234:    *
 235:    * @return the provider of this message digest object.
 236:    */
 237:   public final Provider getProvider()
 238:   {
 239:     return provider;
 240:   }
 241: 
 242:   /**
 243:    * Updates the digest using the specified byte.
 244:    *
 245:    * @param input the byte with which to update the digest.
 246:    */
 247:   public void update(byte input)
 248:   {
 249:     engineUpdate(input);
 250:   }
 251: 
 252:   /**
 253:    * Updates the digest using the specified array of bytes, starting at the
 254:    * specified offset.
 255:    *
 256:    * @param input the array of bytes.
 257:    * @param offset the offset to start from in the array of bytes.
 258:    * @param len the number of bytes to use, starting at offset.
 259:    */
 260:   public void update(byte[] input, int offset, int len)
 261:   {
 262:     engineUpdate(input, offset, len);
 263:   }
 264: 
 265:   /**
 266:    * Updates the digest using the specified array of bytes.
 267:    *
 268:    * @param input the array of bytes.
 269:    */
 270:   public void update(byte[] input)
 271:   {
 272:     engineUpdate(input, 0, input.length);
 273:   }
 274: 
 275:   /**
 276:    * Completes the hash computation by performing final operations such as
 277:    * padding. The digest is reset after this call is made.
 278:    *
 279:    * @return the array of bytes for the resulting hash value.
 280:    */
 281:   public byte[] digest()
 282:   {
 283:     return lastDigest = engineDigest();
 284:   }
 285: 
 286:   /**
 287:    * Completes the hash computation by performing final operations such as
 288:    * padding. The digest is reset after this call is made.
 289:    *
 290:    * @param buf An output buffer for the computed digest.
 291:    * @param offset The offset into the output buffer to begin storing the digest.
 292:    * @param len The number of bytes within buf allotted for the digest.
 293:    * @return The number of bytes placed into buf.
 294:    * @throws DigestException if an error occurs.
 295:    */
 296:   public int digest(byte[] buf, int offset, int len) throws DigestException
 297:   {
 298:     return engineDigest(buf, offset, len);
 299:   }
 300: 
 301:   /**
 302:    * Performs a final update on the digest using the specified array of bytes,
 303:    * then completes the digest computation. That is, this method first calls
 304:    * <code>update(input)</code>, passing the input array to the <code>update()
 305:    * </code> method, then calls <code>digest()</code>.
 306:    *
 307:    * @param input the input to be updated before the digest is completed.
 308:    * @return the array of bytes for the resulting hash value.
 309:    */
 310:   public byte[] digest(byte[] input)
 311:   {
 312:     update(input);
 313:     return digest();
 314:   }
 315: 
 316:   /**
 317:    * Returns a string representation of this message digest object.
 318:    *
 319:    * @return a string representation of the object.
 320:    */
 321:   public String toString()
 322:   {
 323:     return (getClass()).getName() + " Message Digest <" + digestToString() + ">";
 324:   }
 325: 
 326:   /**
 327:    * Compares two digests for equality. Does a simple byte compare.
 328:    *
 329:    * @param digesta one of the digests to compare.
 330:    * @param digestb the other digest to compare.
 331:    * @return <code>true</code> if the digests are equal, <code>false</code>
 332:    * otherwise.
 333:    */
 334:   public static boolean isEqual(byte[] digesta, byte[] digestb)
 335:   {
 336:     if (digesta.length != digestb.length)
 337:       return false;
 338: 
 339:     for (int i = digesta.length - 1; i >= 0; --i)
 340:       if (digesta[i] != digestb[i])
 341:         return false;
 342: 
 343:     return true;
 344:   }
 345: 
 346:   /** Resets the digest for further use. */
 347:   public void reset()
 348:   {
 349:     engineReset();
 350:   }
 351: 
 352:   /**
 353:    * Returns a string that identifies the algorithm, independent of
 354:    * implementation details. The name should be a standard Java Security name
 355:    * (such as <code>"SHA"</code>, <code>"MD5"</code>, and so on). See Appendix
 356:    * A in the Java Cryptography Architecture API Specification &amp; Reference
 357:    * for information about standard algorithm names.
 358:    *
 359:    * @return the name of the algorithm.
 360:    */
 361:   public final String getAlgorithm()
 362:   {
 363:     return algorithm;
 364:   }
 365: 
 366:   /**
 367:    * Returns the length of the digest in bytes, or <code>0</code> if this
 368:    * operation is not supported by the provider and the implementation is not
 369:    * cloneable.
 370:    *
 371:    * @return the digest length in bytes, or <code>0</code> if this operation is
 372:    * not supported by the provider and the implementation is not cloneable.
 373:    * @since 1.2
 374:    */
 375:   public final int getDigestLength()
 376:   {
 377:     return engineGetDigestLength();
 378:   }
 379: 
 380:   /**
 381:    * Returns a clone if the implementation is cloneable.
 382:    *
 383:    * @return a clone if the implementation is cloneable.
 384:    * @throws CloneNotSupportedException if this is called on an implementation
 385:    * that does not support {@link Cloneable}.
 386:    */
 387:   public Object clone() throws CloneNotSupportedException
 388:   {
 389:     return super.clone();
 390:   }
 391: 
 392:   private String digestToString()
 393:   {
 394:     byte[] digest = lastDigest;
 395: 
 396:     if (digest == null)
 397:       return "incomplete";
 398: 
 399:     StringBuffer buf = new StringBuffer();
 400:     int len = digest.length;
 401:     for (int i = 0; i < len; ++i)
 402:       {
 403:         byte b = digest[i];
 404:         byte high = (byte) ((b & 0xff) >>> 4);
 405:         byte low = (byte) (b & 0xf);
 406: 
 407:         buf.append(high > 9 ? ('a' - 10) + high : '0' + high);
 408:         buf.append(low > 9 ? ('a' - 10) + low : '0' + low);
 409:       }
 410: 
 411:     return buf.toString();
 412:   }
 413: }