Source for java.security.MessageDigest

   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:  * <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)
 171:       provider = provider.trim();
 172: 
 173:     if (provider == null || provider.length() == 0)
 174:       throw new IllegalArgumentException("Illegal provider");
 175: 
 176:     Provider p = Security.getProvider(provider);
 177:     if (p == null)
 178:       throw new NoSuchProviderException(provider);
 179: 
 180:     return getInstance(algorithm, p);
 181:   }
 182: 
 183:   /**
 184:    * Generates a <code>MessageDigest</code> object implementing the specified
 185:    * algorithm, as supplied from the specified provider, if such an algorithm
 186:    * is available from the provider. Note: the provider doesn't have to be
 187:    * registered.
 188:    *
 189:    * @param algorithm the name of the algorithm requested. See Appendix A in
 190:    * the Java Cryptography Architecture API Specification &amp; Reference for
 191:    * information about standard algorithm names.
 192:    * @param provider the provider.
 193:    * @return a Message Digest object implementing the specified algorithm.
 194:    * @throws NoSuchAlgorithmException if the <code>algorithm</code> is not
 195:    * available in the package supplied by the requested <code>provider</code>.
 196:    * @throws IllegalArgumentException if the <code>provider</code> is
 197:    * <code>null</code>.
 198:    * @since 1.4
 199:    * @see Provider
 200:    */
 201:   public static MessageDigest getInstance(String algorithm, Provider provider)
 202:     throws NoSuchAlgorithmException
 203:   {
 204:     if (provider == null)
 205:       throw new IllegalArgumentException("Illegal provider");
 206: 
 207:     MessageDigest result = null;
 208:     Object o = null;
 209:     try
 210:       {
 211:         o = Engine.getInstance(MESSAGE_DIGEST, algorithm, provider);
 212:       }
 213:     catch (java.lang.reflect.InvocationTargetException ite)
 214:       {
 215:         throw new NoSuchAlgorithmException(algorithm);
 216:       }
 217: 
 218:     if (o instanceof MessageDigestSpi)
 219:       {
 220:         result = new DummyMessageDigest((MessageDigestSpi) o, algorithm);
 221:       }
 222:     else if (o instanceof MessageDigest)
 223:       {
 224:         result = (MessageDigest) o;
 225:         result.algorithm = algorithm;
 226:       }
 227:     else
 228:       {
 229:         throw new NoSuchAlgorithmException(algorithm);
 230:       }
 231:     result.provider = provider;
 232:     return result;
 233:   }
 234: 
 235:   /**
 236:    * Returns the provider of this message digest object.
 237:    *
 238:    * @return the provider of this message digest object.
 239:    */
 240:   public final Provider getProvider()
 241:   {
 242:     return provider;
 243:   }
 244: 
 245:   /**
 246:    * Updates the digest using the specified byte.
 247:    *
 248:    * @param input the byte with which to update the digest.
 249:    */
 250:   public void update(byte input)
 251:   {
 252:     engineUpdate(input);
 253:   }
 254: 
 255:   /**
 256:    * Updates the digest using the specified array of bytes, starting at the
 257:    * specified offset.
 258:    *
 259:    * @param input the array of bytes.
 260:    * @param offset the offset to start from in the array of bytes.
 261:    * @param len the number of bytes to use, starting at offset.
 262:    */
 263:   public void update(byte[] input, int offset, int len)
 264:   {
 265:     engineUpdate(input, offset, len);
 266:   }
 267: 
 268:   /**
 269:    * Updates the digest using the specified array of bytes.
 270:    *
 271:    * @param input the array of bytes.
 272:    */
 273:   public void update(byte[] input)
 274:   {
 275:     engineUpdate(input, 0, input.length);
 276:   }
 277: 
 278:   /**
 279:    * Completes the hash computation by performing final operations such as
 280:    * padding. The digest is reset after this call is made.
 281:    *
 282:    * @return the array of bytes for the resulting hash value.
 283:    */
 284:   public byte[] digest()
 285:   {
 286:     return lastDigest = engineDigest();
 287:   }
 288: 
 289:   /**
 290:    * Completes the hash computation by performing final operations such as
 291:    * padding. The digest is reset after this call is made.
 292:    *
 293:    * @param buf An output buffer for the computed digest.
 294:    * @param offset The offset into the output buffer to begin storing the digest.
 295:    * @param len The number of bytes within buf allotted for the digest.
 296:    * @return The number of bytes placed into buf.
 297:    * @throws DigestException if an error occurs.
 298:    */
 299:   public int digest(byte[] buf, int offset, int len) throws DigestException
 300:   {
 301:     return engineDigest(buf, offset, len);
 302:   }
 303: 
 304:   /**
 305:    * Performs a final update on the digest using the specified array of bytes,
 306:    * then completes the digest computation. That is, this method first calls
 307:    * <code>update(input)</code>, passing the input array to the <code>update()
 308:    * </code> method, then calls <code>digest()</code>.
 309:    *
 310:    * @param input the input to be updated before the digest is completed.
 311:    * @return the array of bytes for the resulting hash value.
 312:    */
 313:   public byte[] digest(byte[] input)
 314:   {
 315:     update(input);
 316:     return digest();
 317:   }
 318: 
 319:   /**
 320:    * Returns a string representation of this message digest object.
 321:    *
 322:    * @return a string representation of the object.
 323:    */
 324:   public String toString()
 325:   {
 326:     return (getClass()).getName() + " Message Digest <" + digestToString() + ">";
 327:   }
 328: 
 329:   /**
 330:    * Compares two digests for equality. Does a simple byte compare.
 331:    *
 332:    * @param digesta one of the digests to compare.
 333:    * @param digestb the other digest to compare.
 334:    * @return <code>true</code> if the digests are equal, <code>false</code>
 335:    * otherwise.
 336:    */
 337:   public static boolean isEqual(byte[] digesta, byte[] digestb)
 338:   {
 339:     if (digesta.length != digestb.length)
 340:       return false;
 341: 
 342:     for (int i = digesta.length - 1; i >= 0; --i)
 343:       if (digesta[i] != digestb[i])
 344:         return false;
 345: 
 346:     return true;
 347:   }
 348: 
 349:   /** Resets the digest for further use. */
 350:   public void reset()
 351:   {
 352:     engineReset();
 353:   }
 354: 
 355:   /**
 356:    * Returns a string that identifies the algorithm, independent of
 357:    * implementation details. The name should be a standard Java Security name
 358:    * (such as <code>"SHA"</code>, <code>"MD5"</code>, and so on). See Appendix
 359:    * A in the Java Cryptography Architecture API Specification &amp; Reference
 360:    * for information about standard algorithm names.
 361:    *
 362:    * @return the name of the algorithm.
 363:    */
 364:   public final String getAlgorithm()
 365:   {
 366:     return algorithm;
 367:   }
 368: 
 369:   /**
 370:    * Returns the length of the digest in bytes, or <code>0</code> if this
 371:    * operation is not supported by the provider and the implementation is not
 372:    * cloneable.
 373:    *
 374:    * @return the digest length in bytes, or <code>0</code> if this operation is
 375:    * not supported by the provider and the implementation is not cloneable.
 376:    * @since 1.2
 377:    */
 378:   public final int getDigestLength()
 379:   {
 380:     return engineGetDigestLength();
 381:   }
 382: 
 383:   /**
 384:    * Returns a clone if the implementation is cloneable.
 385:    *
 386:    * @return a clone if the implementation is cloneable.
 387:    * @throws CloneNotSupportedException if this is called on an implementation
 388:    * that does not support {@link Cloneable}.
 389:    */
 390:   public Object clone() throws CloneNotSupportedException
 391:   {
 392:     return super.clone();
 393:   }
 394: 
 395:   private String digestToString()
 396:   {
 397:     byte[] digest = lastDigest;
 398: 
 399:     if (digest == null)
 400:       return "incomplete";
 401: 
 402:     StringBuffer buf = new StringBuffer();
 403:     int len = digest.length;
 404:     for (int i = 0; i < len; ++i)
 405:       {
 406:         byte b = digest[i];
 407:         byte high = (byte) ((b & 0xff) >>> 4);
 408:         byte low = (byte) (b & 0xf);
 409: 
 410:         buf.append(high > 9 ? ('a' - 10) + high : '0' + high);
 411:         buf.append(low > 9 ? ('a' - 10) + low : '0' + low);
 412:       }
 413: 
 414:     return buf.toString();
 415:   }
 416: }