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. The 136 * {@code provider} supplied does not have to be registered. 137 * 138 * @param algorithm 139 * the name of the algorithm to use 140 * @param provider 141 * the provider 142 * @return a new instance of {@code MessageDigest} that utilizes the 143 * specified algorithm from the specified provider 144 * @throws NoSuchAlgorithmException 145 * if the specified algorithm is not available 146 * @throws NullPointerException 147 * if {@code algorithm} is {@code null} 148 * @throws IllegalArgumentException if {@code provider == null} 149 */ 150 public static MessageDigest getInstance(String algorithm, Provider provider) 151 throws NoSuchAlgorithmException { 152 if (provider == null) { 153 throw new IllegalArgumentException("provider == null"); 154 } 155 if (algorithm == null) { 156 throw new NullPointerException("algorithm == null"); 157 } 158 Object spi = ENGINE.getInstance(algorithm, provider, null); 159 if (spi instanceof MessageDigest) { 160 MessageDigest result = (MessageDigest) spi; 161 result.algorithm = algorithm; 162 result.provider = provider; 163 return result; 164 } 165 return new MessageDigestImpl((MessageDigestSpi) spi, provider, algorithm); 166 } 167 168 /** 169 * Puts this {@code MessageDigest} back in an initial state, such that it is 170 * ready to compute a one way hash value. 171 */ 172 public void reset() { 173 engineReset(); 174 } 175 176 /** 177 * Updates this {@code MessageDigest} using the given {@code byte}. 178 * 179 * @param arg0 180 * the {@code byte} to update this {@code MessageDigest} with 181 * @see #reset() 182 */ 183 public void update(byte arg0) { 184 engineUpdate(arg0); 185 } 186 187 /** 188 * Updates this {@code MessageDigest} using the given {@code byte[]}. 189 * 190 * @param input 191 * the {@code byte} array 192 * @param offset 193 * the index of the first byte in {@code input} to update from 194 * @param len 195 * the number of bytes in {@code input} to update from 196 * @throws IllegalArgumentException 197 * if {@code offset} or {@code len} are not valid in respect to 198 * {@code input} 199 */ 200 public void update(byte[] input, int offset, int len) { 201 if (input == null || 202 // offset < 0 || len < 0 || 203 // checks for negative values are commented out intentionally 204 // see HARMONY-1120 for details 205 (long) offset + (long) len > input.length) { 206 throw new IllegalArgumentException(); 207 } 208 engineUpdate(input, offset, len); 209 } 210 211 /** 212 * Updates this {@code MessageDigest} using the given {@code byte[]}. 213 * 214 * @param input 215 * the {@code byte} array 216 * @throws NullPointerException 217 * if {@code input} is {@code null} 218 */ 219 public void update(byte[] input) { 220 if (input == null) { 221 throw new NullPointerException("input == null"); 222 } 223 engineUpdate(input, 0, input.length); 224 } 225 226 /** 227 * Computes and returns the final hash value for this {@link MessageDigest}. 228 * After the digest is computed the receiver is reset. 229 * 230 * @return the computed one way hash value 231 * @see #reset 232 */ 233 public byte[] digest() { 234 return engineDigest(); 235 } 236 237 /** 238 * Computes and stores the final hash value for this {@link MessageDigest}. 239 * After the digest is computed the receiver is reset. 240 * 241 * @param buf 242 * the buffer to store the result 243 * @param offset 244 * the index of the first byte in {@code buf} to store 245 * @param len 246 * the number of bytes allocated for the digest 247 * @return the number of bytes written to {@code buf} 248 * @throws DigestException 249 * if an error occurs 250 * @throws IllegalArgumentException 251 * if {@code offset} or {@code len} are not valid in respect to 252 * {@code buf} 253 * @see #reset() 254 */ 255 public int digest(byte[] buf, int offset, int len) throws DigestException { 256 if (buf == null || 257 // offset < 0 || len < 0 || 258 // checks for negative values are commented out intentionally 259 // see HARMONY-1148 for details 260 (long) offset + (long) len > buf.length) { 261 throw new IllegalArgumentException(); 262 } 263 return engineDigest(buf, offset, len); 264 } 265 266 /** 267 * Performs the final update and then computes and returns the final hash 268 * value for this {@link MessageDigest}. After the digest is computed the 269 * receiver is reset. 270 * 271 * @param input 272 * the {@code byte} array 273 * @return the computed one way hash value 274 * @see #reset() 275 */ 276 public byte[] digest(byte[] input) { 277 update(input); 278 return digest(); 279 } 280 281 /** 282 * Returns a string containing a concise, human-readable description of this 283 * {@code MessageDigest} including the name of its algorithm. 284 * 285 * @return a printable representation for this {@code MessageDigest} 286 */ 287 @Override 288 public String toString() { 289 return "MESSAGE DIGEST " + algorithm; 290 } 291 292 /** 293 * Indicates whether to digest are equal by performing a simply 294 * byte-per-byte compare of the two digests. 295 * 296 * @param digesta 297 * the first digest to be compared 298 * @param digestb 299 * the second digest to be compared 300 * @return {@code true} if the two hashes are equal, {@code false} otherwise 301 */ 302 public static boolean isEqual(byte[] digesta, byte[] digestb) { 303 if (digesta.length != digestb.length) { 304 return false; 305 } 306 // Perform a constant time comparison to avoid timing attacks. 307 int v = 0; 308 for (int i = 0; i < digesta.length; i++) { 309 v |= (digesta[i] ^ digestb[i]); 310 } 311 return v == 0; 312 } 313 314 /** 315 * Returns the name of the algorithm of this {@code MessageDigest}. 316 * 317 * @return the name of the algorithm of this {@code MessageDigest} 318 */ 319 public final String getAlgorithm() { 320 return algorithm; 321 } 322 323 /** 324 * Returns the provider associated with this {@code MessageDigest}. 325 * 326 * @return the provider associated with this {@code MessageDigest} 327 */ 328 public final Provider getProvider() { 329 return provider; 330 } 331 332 /** 333 * Returns the engine digest length in bytes. If the implementation does not 334 * implement this function or is not an instance of {@code Cloneable}, 335 * {@code 0} is returned. 336 * 337 * @return the digest length in bytes, or {@code 0} 338 */ 339 public final int getDigestLength() { 340 int l = engineGetDigestLength(); 341 if (l != 0) { 342 return l; 343 } 344 if (!(this instanceof Cloneable)) { 345 return 0; 346 } 347 try { 348 MessageDigest md = (MessageDigest) clone(); 349 return md.digest().length; 350 } catch (CloneNotSupportedException e) { 351 return 0; 352 } 353 } 354 355 /** 356 * Updates this {@code MessageDigest} using the given {@code input}. 357 * 358 * @param input 359 * the {@code ByteBuffer} 360 */ 361 public final void update(ByteBuffer input) { 362 engineUpdate(input); 363 } 364 365 /** 366 * 367 * The internal MessageDigest implementation 368 * 369 */ 370 private static class MessageDigestImpl extends MessageDigest { 371 372 // MessageDigestSpi implementation 373 private MessageDigestSpi spiImpl; 374 375 // MessageDigestImpl ctor 376 private MessageDigestImpl(MessageDigestSpi messageDigestSpi, 377 Provider provider, String algorithm) { 378 super(algorithm); 379 super.provider = provider; 380 spiImpl = messageDigestSpi; 381 } 382 383 // engineReset() implementation 384 @Override 385 protected void engineReset() { 386 spiImpl.engineReset(); 387 } 388 389 // engineDigest() implementation 390 @Override 391 protected byte[] engineDigest() { 392 return spiImpl.engineDigest(); 393 } 394 395 // engineGetDigestLength() implementation 396 @Override 397 protected int engineGetDigestLength() { 398 return spiImpl.engineGetDigestLength(); 399 } 400 401 // engineUpdate() implementation 402 @Override 403 protected void engineUpdate(byte arg0) { 404 spiImpl.engineUpdate(arg0); 405 } 406 407 // engineUpdate() implementation 408 @Override 409 protected void engineUpdate(byte[] arg0, int arg1, int arg2) { 410 spiImpl.engineUpdate(arg0, arg1, arg2); 411 } 412 413 // Returns a clone if the spiImpl is cloneable 414 @Override 415 public Object clone() throws CloneNotSupportedException { 416 MessageDigestSpi spi = (MessageDigestSpi) spiImpl.clone(); 417 return new MessageDigestImpl(spi, getProvider(), getAlgorithm()); 418 } 419 } 420} 421