/* * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.security; import java.util.*; import java.lang.*; import java.io.IOException; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.InputStream; import java.io.ByteArrayInputStream; import java.nio.ByteBuffer; /* Android-removed: this debugging mechanism is not available in Android. import sun.security.util.Debug; */ /** * This MessageDigest class provides applications the functionality of a * message digest algorithm, such as SHA-1 or SHA-256. * Message digests are secure one-way hash functions that take arbitrary-sized * data and output a fixed-length hash value. * *
A MessageDigest object starts out initialized. The data is * processed through it using the {@link #update(byte) update} * methods. At any point {@link #reset() reset} can be called * to reset the digest. Once all the data to be updated has been * updated, one of the {@link #digest() digest} methods should * be called to complete the hash computation. * *
The {@code digest} method can be called once for a given number * of updates. After {@code digest} has been called, the MessageDigest * object is reset to its initialized state. * *
Implementations are free to implement the Cloneable interface. * Client applications can test cloneability by attempting cloning * and catching the CloneNotSupportedException: * *
{@code * MessageDigest md = MessageDigest.getInstance("SHA"); * * try { * md.update(toChapter1); * MessageDigest tc1 = md.clone(); * byte[] toChapter1Digest = tc1.digest(); * md.update(toChapter2); * ...etc. * } catch (CloneNotSupportedException cnse) { * throw new DigestException("couldn't make digest of partial content"); * } * }* *
Note that if a given implementation is not cloneable, it is * still possible to compute intermediate digests by instantiating * several instances, if the number of digests is known in advance. * *
Note that this class is abstract and extends from * {@code MessageDigestSpi} for historical reasons. * Application developers should only take notice of the methods defined in * this {@code MessageDigest} class; all the methods in * the superclass are intended for cryptographic service providers who wish to * supply their own implementations of message digest algorithms. * *
Android provides the following MessageDigest
algorithms:
*
Algorithm | *Supported API Levels | *
---|---|
MD5 | *1+ | *
SHA-1 | *1+ | *
SHA-224 | *1-8,22+ | *
SHA-256 | *1+ | *
SHA-384 | *1+ | *
SHA-512 | *1+ | *
This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new MessageDigest object encapsulating the * MessageDigestSpi implementation from the first * Provider that supports the specified algorithm is returned. * *
Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return a Message Digest object that implements the specified algorithm. * * @exception NoSuchAlgorithmException if no Provider supports a * MessageDigestSpi implementation for the * specified algorithm. * * @see Provider */ public static MessageDigest getInstance(String algorithm) throws NoSuchAlgorithmException { try { MessageDigest md; Object[] objs = Security.getImpl(algorithm, "MessageDigest", (String)null); if (objs[0] instanceof MessageDigest) { md = (MessageDigest)objs[0]; } else { md = new Delegate((MessageDigestSpi)objs[0], algorithm); } md.provider = (Provider)objs[1]; /* Android-removed: this debugging mechanism is not available in Android. if (!skipDebug && pdebug != null) { pdebug.println("MessageDigest." + algorithm + " algorithm from: " + md.provider.getName()); } */ return md; } catch(NoSuchProviderException e) { throw new NoSuchAlgorithmException(algorithm + " not found"); } } /** * Returns a MessageDigest object that implements the specified digest * algorithm. * *
A new MessageDigest object encapsulating the * MessageDigestSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *
Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. * See the MessageDigest section in the * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. * * @return a MessageDigest object that implements the specified algorithm. * * @exception NoSuchAlgorithmException if a MessageDigestSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider name is null * or empty. * * @see Provider */ public static MessageDigest getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { if (provider == null || provider.length() == 0) throw new IllegalArgumentException("missing provider"); Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider); if (objs[0] instanceof MessageDigest) { MessageDigest md = (MessageDigest)objs[0]; md.provider = (Provider)objs[1]; return md; } else { MessageDigest delegate = new Delegate((MessageDigestSpi)objs[0], algorithm); delegate.provider = (Provider)objs[1]; return delegate; } } /** * Returns a MessageDigest object that implements the specified digest * algorithm. * *
A new MessageDigest object encapsulating the
* MessageDigestSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the name of the algorithm requested.
* See the MessageDigest section in the
* Java Cryptography Architecture Standard Algorithm Name Documentation
* for information about standard algorithm names.
*
* @param provider the provider.
*
* @return a MessageDigest object that implements the specified algorithm.
*
* @exception NoSuchAlgorithmException if a MessageDigestSpi
* implementation for the specified algorithm is not available
* from the specified Provider object.
*
* @exception IllegalArgumentException if the specified provider is null.
*
* @see Provider
*
* @since 1.4
*/
public static MessageDigest getInstance(String algorithm,
Provider provider)
throws NoSuchAlgorithmException
{
if (provider == null)
throw new IllegalArgumentException("missing provider");
Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
if (objs[0] instanceof MessageDigest) {
MessageDigest md = (MessageDigest)objs[0];
md.provider = (Provider)objs[1];
return md;
} else {
MessageDigest delegate =
new Delegate((MessageDigestSpi)objs[0], algorithm);
delegate.provider = (Provider)objs[1];
return delegate;
}
}
/**
* Returns the provider of this message digest object.
*
* @return the provider of this message digest object
*/
public final Provider getProvider() {
return this.provider;
}
/**
* Updates the digest using the specified byte.
*
* @param input the byte with which to update the digest.
*/
public void update(byte input) {
engineUpdate(input);
state = IN_PROGRESS;
}
/**
* Updates the digest using the specified array of bytes, starting
* at the specified offset.
*
* @param input the array of bytes.
*
* @param offset the offset to start from in the array of bytes.
*
* @param len the number of bytes to use, starting at
* {@code offset}.
*/
public void update(byte[] input, int offset, int len) {
if (input == null) {
throw new IllegalArgumentException("No input buffer given");
}
if (input.length - offset < len) {
throw new IllegalArgumentException("Input buffer too short");
}
engineUpdate(input, offset, len);
state = IN_PROGRESS;
}
/**
* Updates the digest using the specified array of bytes.
*
* @param input the array of bytes.
*/
public void update(byte[] input) {
engineUpdate(input, 0, input.length);
state = IN_PROGRESS;
}
/**
* Update the digest using the specified ByteBuffer. The digest is
* updated using the {@code input.remaining()} bytes starting
* at {@code input.position()}.
* Upon return, the buffer's position will be equal to its limit;
* its limit will not have changed.
*
* @param input the ByteBuffer
* @since 1.5
*/
public final void update(ByteBuffer input) {
if (input == null) {
throw new NullPointerException();
}
engineUpdate(input);
state = IN_PROGRESS;
}
/**
* Completes the hash computation by performing final operations
* such as padding. The digest is reset after this call is made.
*
* @return the array of bytes for the resulting hash value.
*/
public byte[] digest() {
/* Resetting is the responsibility of implementors. */
byte[] result = engineDigest();
state = INITIAL;
return result;
}
/**
* Completes the hash computation by performing final operations
* such as padding. The digest is reset after this call is made.
*
* @param buf output buffer for the computed digest
*
* @param offset offset into the output buffer to begin storing the digest
*
* @param len number of bytes within buf allotted for the digest
*
* @return the number of bytes placed into {@code buf}
*
* @exception DigestException if an error occurs.
*/
public int digest(byte[] buf, int offset, int len) throws DigestException {
if (buf == null) {
throw new IllegalArgumentException("No output buffer given");
}
if (buf.length - offset < len) {
throw new IllegalArgumentException
("Output buffer too small for specified offset and length");
}
int numBytes = engineDigest(buf, offset, len);
state = INITIAL;
return numBytes;
}
/**
* Performs a final update on the digest using the specified array
* of bytes, then completes the digest computation. That is, this
* method first calls {@link #update(byte[]) update(input)},
* passing the input array to the {@code update} method,
* then calls {@link #digest() digest()}.
*
* @param input the input to be updated before the digest is
* completed.
*
* @return the array of bytes for the resulting hash value.
*/
public byte[] digest(byte[] input) {
update(input);
return digest();
}
/**
* Returns a string representation of this message digest object.
*/
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(algorithm);
builder.append(" Message Digest from ");
builder.append(provider.getName());
builder.append(", ");
switch (state) {
case INITIAL:
builder.append("