1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.security; 19 20import java.nio.ByteBuffer; 21import org.apache.harmony.security.fortress.Engine; 22 23/** 24 * Uses a one-way hash function to turn an arbitrary number of bytes into a 25 * fixed-length byte sequence. The original arbitrary-length sequence is the 26 * <i>message</i>, and the fixed-length byte sequence is the <i>digest</i> or 27 * <i>message digest</i>. 28 * 29 * <h4>Sample Code</h4> 30 * <p>The basic pattern to digest an {@link java.io.InputStream} looks like this: 31 * <pre> 32 * MessageDigest digester = MessageDigest.getInstance("MD5"); 33 * byte[] bytes = new byte[8192]; 34 * int byteCount; 35 * while ((byteCount = in.read(bytes)) > 0) { 36 * digester.update(bytes, 0, byteCount); 37 * } 38 * byte[] digest = digester.digest(); 39 * </pre> 40 * 41 * <p>That is, after creating or resetting a {@code MessageDigest} you should 42 * call {@link #update(byte[],int,int)} for each block of input data, and then call {@link #digest} 43 * to get the final digest. Note that calling {@code digest} resets the {@code MessageDigest}. 44 * Advanced users who want partial digests should clone their {@code MessageDigest} before 45 * calling {@code digest}. 46 * 47 * <p>This class is not thread-safe. 48 * 49 * @see MessageDigestSpi 50 */ 51public abstract class MessageDigest extends MessageDigestSpi { 52 53 // Used to access common engine functionality 54 private static final Engine ENGINE = new Engine("MessageDigest"); 55 56 // The provider 57 private Provider provider; 58 59 // The algorithm. 60 private String algorithm; 61 62 /** 63 * Constructs a new instance of {@code MessageDigest} with the name of 64 * the algorithm to use. 65 * 66 * @param algorithm 67 * the name of algorithm to use 68 */ 69 protected MessageDigest(String algorithm) { 70 this.algorithm = algorithm; 71 } 72 73 /** 74 * Returns a new instance of {@code MessageDigest} that utilizes the 75 * specified algorithm. 76 * 77 * @param algorithm 78 * the name of the algorithm to use 79 * @return a new instance of {@code MessageDigest} that utilizes the 80 * specified algorithm 81 * @throws NoSuchAlgorithmException 82 * if the specified algorithm is not available 83 * @throws NullPointerException 84 * if {@code algorithm} is {@code null} 85 */ 86 public static MessageDigest getInstance(String algorithm) 87 throws NoSuchAlgorithmException { 88 if (algorithm == null) { 89 throw new NullPointerException("algorithm == null"); 90 } 91 Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null); 92 Object spi = sap.spi; 93 Provider provider = sap.provider; 94 if (spi instanceof MessageDigest) { 95 MessageDigest result = (MessageDigest) spi; 96 result.algorithm = algorithm; 97 result.provider = provider; 98 return result; 99 } 100 return new MessageDigestImpl((MessageDigestSpi) sap.spi, sap.provider, algorithm); 101 } 102 103 /** 104 * Returns a new instance of {@code MessageDigest} that utilizes the 105 * specified algorithm from the specified provider. 106 * 107 * @param algorithm 108 * the name of the algorithm to use 109 * @param provider 110 * the name of the provider 111 * @return a new instance of {@code MessageDigest} that utilizes the 112 * specified algorithm from the specified provider 113 * @throws NoSuchAlgorithmException 114 * if the specified algorithm is not available 115 * @throws NoSuchProviderException 116 * if the specified provider is not available 117 * @throws NullPointerException 118 * if {@code algorithm} is {@code null} 119 * @throws IllegalArgumentException if {@code provider == null || provider.isEmpty()} 120 */ 121 public static MessageDigest getInstance(String algorithm, String provider) 122 throws NoSuchAlgorithmException, NoSuchProviderException { 123 if (provider == null || provider.isEmpty()) { 124 throw new IllegalArgumentException(); 125 } 126 Provider p = Security.getProvider(provider); 127 if (p == null) { 128 throw new NoSuchProviderException(provider); 129 } 130 return getInstance(algorithm, p); 131 } 132 133 /** 134 * Returns a new instance of {@code MessageDigest} that utilizes the 135 * specified algorithm from the specified provider. 136 * 137 * @param algorithm 138 * the name of the algorithm to use 139 * @param provider 140 * the provider 141 * @return a new instance of {@code MessageDigest} that utilizes the 142 * specified algorithm from the specified provider 143 * @throws NoSuchAlgorithmException 144 * if the specified algorithm is not available 145 * @throws NullPointerException 146 * if {@code algorithm} is {@code null} 147 * @throws IllegalArgumentException if {@code provider == null} 148 */ 149 public static MessageDigest getInstance(String algorithm, Provider provider) 150 throws NoSuchAlgorithmException { 151 if (provider == null) { 152 throw new IllegalArgumentException("provider == null"); 153 } 154 if (algorithm == null) { 155 throw new NullPointerException("algorithm == null"); 156 } 157 Object spi = ENGINE.getInstance(algorithm, provider, null); 158 if (spi instanceof MessageDigest) { 159 MessageDigest result = (MessageDigest) spi; 160 result.algorithm = algorithm; 161 result.provider = provider; 162 return result; 163 } 164 return new MessageDigestImpl((MessageDigestSpi) spi, provider, algorithm); 165 } 166 167 /** 168 * Puts this {@code MessageDigest} back in an initial state, such that it is 169 * ready to compute a one way hash value. 170 */ 171 public void reset() { 172 engineReset(); 173 } 174 175 /** 176 * Updates this {@code MessageDigest} using the given {@code byte}. 177 * 178 * @param arg0 179 * the {@code byte} to update this {@code MessageDigest} with 180 * @see #reset() 181 */ 182 public void update(byte arg0) { 183 engineUpdate(arg0); 184 } 185 186 /** 187 * Updates this {@code MessageDigest} using the given {@code byte[]}. 188 * 189 * @param input 190 * the {@code byte} array 191 * @param offset 192 * the index of the first byte in {@code input} to update from 193 * @param len 194 * the number of bytes in {@code input} to update from 195 * @throws IllegalArgumentException 196 * if {@code offset} or {@code len} are not valid in respect to 197 * {@code input} 198 */ 199 public void update(byte[] input, int offset, int len) { 200 if (input == null || 201 // offset < 0 || len < 0 || 202 // checks for negative values are commented out intentionally 203 // see HARMONY-1120 for details 204 (long) offset + (long) len > input.length) { 205 throw new IllegalArgumentException(); 206 } 207 engineUpdate(input, offset, len); 208 } 209 210 /** 211 * Updates this {@code MessageDigest} using the given {@code byte[]}. 212 * 213 * @param input 214 * the {@code byte} array 215 * @throws NullPointerException 216 * if {@code input} is {@code null} 217 */ 218 public void update(byte[] input) { 219 if (input == null) { 220 throw new NullPointerException("input == null"); 221 } 222 engineUpdate(input, 0, input.length); 223 } 224 225 /** 226 * Computes and returns the final hash value for this {@link MessageDigest}. 227 * After the digest is computed the receiver is reset. 228 * 229 * @return the computed one way hash value 230 * @see #reset 231 */ 232 public byte[] digest() { 233 return engineDigest(); 234 } 235 236 /** 237 * Computes and stores the final hash value for this {@link MessageDigest}. 238 * After the digest is computed the receiver is reset. 239 * 240 * @param buf 241 * the buffer to store the result 242 * @param offset 243 * the index of the first byte in {@code buf} to store 244 * @param len 245 * the number of bytes allocated for the digest 246 * @return the number of bytes written to {@code buf} 247 * @throws DigestException 248 * if an error occurs 249 * @throws IllegalArgumentException 250 * if {@code offset} or {@code len} are not valid in respect to 251 * {@code buf} 252 * @see #reset() 253 */ 254 public int digest(byte[] buf, int offset, int len) throws DigestException { 255 if (buf == null || 256 // offset < 0 || len < 0 || 257 // checks for negative values are commented out intentionally 258 // see HARMONY-1148 for details 259 (long) offset + (long) len > buf.length) { 260 throw new IllegalArgumentException(); 261 } 262 return engineDigest(buf, offset, len); 263 } 264 265 /** 266 * Performs the final update and then computes and returns the final hash 267 * value for this {@link MessageDigest}. After the digest is computed the 268 * receiver is reset. 269 * 270 * @param input 271 * the {@code byte} array 272 * @return the computed one way hash value 273 * @see #reset() 274 */ 275 public byte[] digest(byte[] input) { 276 update(input); 277 return digest(); 278 } 279 280 /** 281 * Returns a string containing a concise, human-readable description of this 282 * {@code MessageDigest} including the name of its algorithm. 283 * 284 * @return a printable representation for this {@code MessageDigest} 285 */ 286 @Override 287 public String toString() { 288 return "MESSAGE DIGEST " + algorithm; 289 } 290 291 /** 292 * Indicates whether to digest are equal by performing a simply 293 * byte-per-byte compare of the two digests. 294 * 295 * @param digesta 296 * the first digest to be compared 297 * @param digestb 298 * the second digest to be compared 299 * @return {@code true} if the two hashes are equal, {@code false} otherwise 300 */ 301 public static boolean isEqual(byte[] digesta, byte[] digestb) { 302 if (digesta.length != digestb.length) { 303 return false; 304 } 305 for (int i = 0; i < digesta.length; i++) { 306 if (digesta[i] != digestb[i]) { 307 return false; 308 } 309 } 310 return true; 311 } 312 313 /** 314 * Returns the name of the algorithm of this {@code MessageDigest}. 315 * 316 * @return the name of the algorithm of this {@code MessageDigest} 317 */ 318 public final String getAlgorithm() { 319 return algorithm; 320 } 321 322 /** 323 * Returns the provider associated with this {@code MessageDigest}. 324 * 325 * @return the provider associated with this {@code MessageDigest} 326 */ 327 public final Provider getProvider() { 328 return provider; 329 } 330 331 /** 332 * Returns the engine digest length in bytes. If the implementation does not 333 * implement this function or is not an instance of {@code Cloneable}, 334 * {@code 0} is returned. 335 * 336 * @return the digest length in bytes, or {@code 0} 337 */ 338 public final int getDigestLength() { 339 int l = engineGetDigestLength(); 340 if (l != 0) { 341 return l; 342 } 343 if (!(this instanceof Cloneable)) { 344 return 0; 345 } 346 try { 347 MessageDigest md = (MessageDigest) clone(); 348 return md.digest().length; 349 } catch (CloneNotSupportedException e) { 350 return 0; 351 } 352 } 353 354 @Override 355 public Object clone() throws CloneNotSupportedException { 356 if (this instanceof Cloneable) { 357 return super.clone(); 358 } 359 throw new CloneNotSupportedException(); 360 } 361 362 /** 363 * Updates this {@code MessageDigest} using the given {@code input}. 364 * 365 * @param input 366 * the {@code ByteBuffer} 367 */ 368 public final void update(ByteBuffer input) { 369 engineUpdate(input); 370 } 371 372 /** 373 * 374 * The internal MessageDigest implementation 375 * 376 */ 377 private static class MessageDigestImpl extends MessageDigest { 378 379 // MessageDigestSpi implementation 380 private MessageDigestSpi spiImpl; 381 382 // MessageDigestImpl ctor 383 private MessageDigestImpl(MessageDigestSpi messageDigestSpi, 384 Provider provider, String algorithm) { 385 super(algorithm); 386 super.provider = provider; 387 spiImpl = messageDigestSpi; 388 } 389 390 // engineReset() implementation 391 @Override 392 protected void engineReset() { 393 spiImpl.engineReset(); 394 } 395 396 // engineDigest() implementation 397 @Override 398 protected byte[] engineDigest() { 399 return spiImpl.engineDigest(); 400 } 401 402 // engineGetDigestLength() implementation 403 @Override 404 protected int engineGetDigestLength() { 405 return spiImpl.engineGetDigestLength(); 406 } 407 408 // engineUpdate() implementation 409 @Override 410 protected void engineUpdate(byte arg0) { 411 spiImpl.engineUpdate(arg0); 412 } 413 414 // engineUpdate() implementation 415 @Override 416 protected void engineUpdate(byte[] arg0, int arg1, int arg2) { 417 spiImpl.engineUpdate(arg0, arg1, arg2); 418 } 419 420 // Returns a clone if the spiImpl is cloneable 421 @Override 422 public Object clone() throws CloneNotSupportedException { 423 if (spiImpl instanceof Cloneable) { 424 MessageDigestSpi spi = (MessageDigestSpi) spiImpl.clone(); 425 return new MessageDigestImpl(spi, getProvider(), getAlgorithm()); 426 } 427 428 throw new CloneNotSupportedException(); 429 } 430 } 431} 432