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