Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/security/MessageDigest.java
38829 views
/*1* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.security;2627import java.util.*;28import java.lang.*;29import java.io.IOException;30import java.io.ByteArrayOutputStream;31import java.io.PrintStream;32import java.io.InputStream;33import java.io.ByteArrayInputStream;34import java.security.InvalidKeyException;35import java.nio.ByteBuffer;3637import sun.security.util.Debug;38import sun.security.util.MessageDigestSpi2;3940import javax.crypto.SecretKey;4142/**43* This MessageDigest class provides applications the functionality of a44* message digest algorithm, such as SHA-1 or SHA-256.45* Message digests are secure one-way hash functions that take arbitrary-sized46* data and output a fixed-length hash value.47*48* <p>A MessageDigest object starts out initialized. The data is49* processed through it using the {@link #update(byte) update}50* methods. At any point {@link #reset() reset} can be called51* to reset the digest. Once all the data to be updated has been52* updated, one of the {@link #digest() digest} methods should53* be called to complete the hash computation.54*55* <p>The {@code digest} method can be called once for a given number56* of updates. After {@code digest} has been called, the MessageDigest57* object is reset to its initialized state.58*59* <p>Implementations are free to implement the Cloneable interface.60* Client applications can test cloneability by attempting cloning61* and catching the CloneNotSupportedException:62*63* <pre>{@code64* MessageDigest md = MessageDigest.getInstance("SHA-256");65*66* try {67* md.update(toChapter1);68* MessageDigest tc1 = md.clone();69* byte[] toChapter1Digest = tc1.digest();70* md.update(toChapter2);71* ...etc.72* } catch (CloneNotSupportedException cnse) {73* throw new DigestException("couldn't make digest of partial content");74* }75* }</pre>76*77* <p>Note that if a given implementation is not cloneable, it is78* still possible to compute intermediate digests by instantiating79* several instances, if the number of digests is known in advance.80*81* <p>Note that this class is abstract and extends from82* {@code MessageDigestSpi} for historical reasons.83* Application developers should only take notice of the methods defined in84* this {@code MessageDigest} class; all the methods in85* the superclass are intended for cryptographic service providers who wish to86* supply their own implementations of message digest algorithms.87*88* <p> Every implementation of the Java platform is required to support89* the following standard {@code MessageDigest} algorithms:90* <ul>91* <li>{@code MD5}</li>92* <li>{@code SHA-1}</li>93* <li>{@code SHA-256}</li>94* </ul>95* These algorithms are described in the <a href=96* "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">97* MessageDigest section</a> of the98* Java Cryptography Architecture Standard Algorithm Name Documentation.99* Consult the release documentation for your implementation to see if any100* other algorithms are supported.101*102* @author Benjamin Renaud103*104* @see DigestInputStream105* @see DigestOutputStream106*/107108public abstract class MessageDigest extends MessageDigestSpi {109110private static final Debug pdebug =111Debug.getInstance("provider", "Provider");112private static final boolean skipDebug =113Debug.isOn("engine=") && !Debug.isOn("messagedigest");114115private String algorithm;116117// The state of this digest118private static final int INITIAL = 0;119private static final int IN_PROGRESS = 1;120private int state = INITIAL;121122// The provider123private Provider provider;124125/**126* Creates a message digest with the specified algorithm name.127*128* @param algorithm the standard name of the digest algorithm.129* See the MessageDigest section in the <a href=130* "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">131* Java Cryptography Architecture Standard Algorithm Name Documentation</a>132* for information about standard algorithm names.133*/134protected MessageDigest(String algorithm) {135this.algorithm = algorithm;136}137138/**139* Returns a MessageDigest object that implements the specified digest140* algorithm.141*142* <p> This method traverses the list of registered security Providers,143* starting with the most preferred Provider.144* A new MessageDigest object encapsulating the145* MessageDigestSpi implementation from the first146* Provider that supports the specified algorithm is returned.147*148* <p> Note that the list of registered providers may be retrieved via149* the {@link Security#getProviders() Security.getProviders()} method.150*151* @param algorithm the name of the algorithm requested.152* See the MessageDigest section in the <a href=153* "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">154* Java Cryptography Architecture Standard Algorithm Name Documentation</a>155* for information about standard algorithm names.156*157* @return a Message Digest object that implements the specified algorithm.158*159* @exception NoSuchAlgorithmException if no Provider supports a160* MessageDigestSpi implementation for the161* specified algorithm.162*163* @see Provider164*/165public static MessageDigest getInstance(String algorithm)166throws NoSuchAlgorithmException {167try {168MessageDigest md;169Object[] objs = Security.getImpl(algorithm, "MessageDigest",170(String)null);171if (objs[0] instanceof MessageDigest) {172md = (MessageDigest)objs[0];173} else {174md = new Delegate((MessageDigestSpi)objs[0], algorithm);175}176md.provider = (Provider)objs[1];177178if (!skipDebug && pdebug != null) {179pdebug.println("MessageDigest." + algorithm +180" algorithm from: " + md.provider.getName());181}182183return md;184185} catch(NoSuchProviderException e) {186throw new NoSuchAlgorithmException(algorithm + " not found");187}188}189190/**191* Returns a MessageDigest object that implements the specified digest192* algorithm.193*194* <p> A new MessageDigest object encapsulating the195* MessageDigestSpi implementation from the specified provider196* is returned. The specified provider must be registered197* in the security provider list.198*199* <p> Note that the list of registered providers may be retrieved via200* the {@link Security#getProviders() Security.getProviders()} method.201*202* @param algorithm the name of the algorithm requested.203* See the MessageDigest section in the <a href=204* "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">205* Java Cryptography Architecture Standard Algorithm Name Documentation</a>206* for information about standard algorithm names.207*208* @param provider the name of the provider.209*210* @return a MessageDigest object that implements the specified algorithm.211*212* @exception NoSuchAlgorithmException if a MessageDigestSpi213* implementation for the specified algorithm is not214* available from the specified provider.215*216* @exception NoSuchProviderException if the specified provider is not217* registered in the security provider list.218*219* @exception IllegalArgumentException if the provider name is null220* or empty.221*222* @see Provider223*/224public static MessageDigest getInstance(String algorithm, String provider)225throws NoSuchAlgorithmException, NoSuchProviderException226{227if (provider == null || provider.length() == 0)228throw new IllegalArgumentException("missing provider");229Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);230if (objs[0] instanceof MessageDigest) {231MessageDigest md = (MessageDigest)objs[0];232md.provider = (Provider)objs[1];233return md;234} else {235MessageDigest delegate =236new Delegate((MessageDigestSpi)objs[0], algorithm);237delegate.provider = (Provider)objs[1];238return delegate;239}240}241242/**243* Returns a MessageDigest object that implements the specified digest244* algorithm.245*246* <p> A new MessageDigest object encapsulating the247* MessageDigestSpi implementation from the specified Provider248* object is returned. Note that the specified Provider object249* does not have to be registered in the provider list.250*251* @param algorithm the name of the algorithm requested.252* See the MessageDigest section in the <a href=253* "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">254* Java Cryptography Architecture Standard Algorithm Name Documentation</a>255* for information about standard algorithm names.256*257* @param provider the provider.258*259* @return a MessageDigest object that implements the specified algorithm.260*261* @exception NoSuchAlgorithmException if a MessageDigestSpi262* implementation for the specified algorithm is not available263* from the specified Provider object.264*265* @exception IllegalArgumentException if the specified provider is null.266*267* @see Provider268*269* @since 1.4270*/271public static MessageDigest getInstance(String algorithm,272Provider provider)273throws NoSuchAlgorithmException274{275if (provider == null)276throw new IllegalArgumentException("missing provider");277Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);278if (objs[0] instanceof MessageDigest) {279MessageDigest md = (MessageDigest)objs[0];280md.provider = (Provider)objs[1];281return md;282} else {283MessageDigest delegate =284new Delegate((MessageDigestSpi)objs[0], algorithm);285delegate.provider = (Provider)objs[1];286return delegate;287}288}289290/**291* Returns the provider of this message digest object.292*293* @return the provider of this message digest object294*/295public final Provider getProvider() {296return this.provider;297}298299/**300* Updates the digest using the specified byte.301*302* @param input the byte with which to update the digest.303*/304public void update(byte input) {305engineUpdate(input);306state = IN_PROGRESS;307}308309/**310* Updates the digest using the specified array of bytes, starting311* at the specified offset.312*313* @param input the array of bytes.314*315* @param offset the offset to start from in the array of bytes.316*317* @param len the number of bytes to use, starting at318* {@code offset}.319*/320public void update(byte[] input, int offset, int len) {321if (input == null) {322throw new IllegalArgumentException("No input buffer given");323}324if (input.length - offset < len) {325throw new IllegalArgumentException("Input buffer too short");326}327engineUpdate(input, offset, len);328state = IN_PROGRESS;329}330331/**332* Updates the digest using the specified array of bytes.333*334* @param input the array of bytes.335*/336public void update(byte[] input) {337engineUpdate(input, 0, input.length);338state = IN_PROGRESS;339}340341/**342* Update the digest using the specified ByteBuffer. The digest is343* updated using the {@code input.remaining()} bytes starting344* at {@code input.position()}.345* Upon return, the buffer's position will be equal to its limit;346* its limit will not have changed.347*348* @param input the ByteBuffer349* @since 1.5350*/351public final void update(ByteBuffer input) {352if (input == null) {353throw new NullPointerException();354}355engineUpdate(input);356state = IN_PROGRESS;357}358359/**360* Completes the hash computation by performing final operations361* such as padding. The digest is reset after this call is made.362*363* @return the array of bytes for the resulting hash value.364*/365public byte[] digest() {366/* Resetting is the responsibility of implementors. */367byte[] result = engineDigest();368state = INITIAL;369return result;370}371372/**373* Completes the hash computation by performing final operations374* such as padding. The digest is reset after this call is made.375*376* @param buf output buffer for the computed digest377*378* @param offset offset into the output buffer to begin storing the digest379*380* @param len number of bytes within buf allotted for the digest381*382* @return the number of bytes placed into {@code buf}383*384* @exception DigestException if an error occurs.385*/386public int digest(byte[] buf, int offset, int len) throws DigestException {387if (buf == null) {388throw new IllegalArgumentException("No output buffer given");389}390if (buf.length - offset < len) {391throw new IllegalArgumentException392("Output buffer too small for specified offset and length");393}394int numBytes = engineDigest(buf, offset, len);395state = INITIAL;396return numBytes;397}398399/**400* Performs a final update on the digest using the specified array401* of bytes, then completes the digest computation. That is, this402* method first calls {@link #update(byte[]) update(input)},403* passing the <i>input</i> array to the {@code update} method,404* then calls {@link #digest() digest()}.405*406* @param input the input to be updated before the digest is407* completed.408*409* @return the array of bytes for the resulting hash value.410*/411public byte[] digest(byte[] input) {412update(input);413return digest();414}415416/**417* Returns a string representation of this message digest object.418*/419public String toString() {420ByteArrayOutputStream baos = new ByteArrayOutputStream();421PrintStream p = new PrintStream(baos);422p.print(algorithm+" Message Digest from "+provider.getName()+", ");423switch (state) {424case INITIAL:425p.print("<initialized>");426break;427case IN_PROGRESS:428p.print("<in progress>");429break;430}431p.println();432return (baos.toString());433}434435/**436* Compares two digests for equality. Does a simple byte compare.437*438* @implNote439* All bytes in {@code digesta} are examined to determine equality.440* The calculation time depends only on the length of {@code digesta}.441* It does not depend on the length of {@code digestb} or the contents442* of {@code digesta} and {@code digestb}.443*444* @param digesta one of the digests to compare.445*446* @param digestb the other digest to compare.447*448* @return true if the digests are equal, false otherwise.449*/450public static boolean isEqual(byte[] digesta, byte[] digestb) {451if (digesta == digestb) return true;452if (digesta == null || digestb == null) {453return false;454}455456int lenA = digesta.length;457int lenB = digestb.length;458459if (lenB == 0) {460return lenA == 0;461}462463int result = 0;464result |= lenA - lenB;465466// time-constant comparison467for (int i = 0; i < lenA; i++) {468// If i >= lenB, indexB is 0; otherwise, i.469int indexB = ((i - lenB) >>> 31) * i;470result |= digesta[i] ^ digestb[indexB];471}472return result == 0;473}474475/**476* Resets the digest for further use.477*/478public void reset() {479engineReset();480state = INITIAL;481}482483/**484* Returns a string that identifies the algorithm, independent of485* implementation details. The name should be a standard486* Java Security name (such as "SHA-256").487* See the MessageDigest section in the <a href=488* "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">489* Java Cryptography Architecture Standard Algorithm Name Documentation</a>490* for information about standard algorithm names.491*492* @return the name of the algorithm493*/494public final String getAlgorithm() {495return this.algorithm;496}497498/**499* Returns the length of the digest in bytes, or 0 if this operation is500* not supported by the provider and the implementation is not cloneable.501*502* @return the digest length in bytes, or 0 if this operation is not503* supported by the provider and the implementation is not cloneable.504*505* @since 1.2506*/507public final int getDigestLength() {508int digestLen = engineGetDigestLength();509if (digestLen == 0) {510try {511MessageDigest md = (MessageDigest)clone();512byte[] digest = md.digest();513return digest.length;514} catch (CloneNotSupportedException e) {515return digestLen;516}517}518return digestLen;519}520521/**522* Returns a clone if the implementation is cloneable.523*524* @return a clone if the implementation is cloneable.525*526* @exception CloneNotSupportedException if this is called on an527* implementation that does not support {@code Cloneable}.528*/529public Object clone() throws CloneNotSupportedException {530if (this instanceof Cloneable) {531return super.clone();532} else {533throw new CloneNotSupportedException();534}535}536537538539540/*541* The following class allows providers to extend from MessageDigestSpi542* rather than from MessageDigest. It represents a MessageDigest with an543* encapsulated, provider-supplied SPI object (of type MessageDigestSpi).544* If the provider implementation is an instance of MessageDigestSpi,545* the getInstance() methods above return an instance of this class, with546* the SPI object encapsulated.547*548* Note: All SPI methods from the original MessageDigest class have been549* moved up the hierarchy into a new class (MessageDigestSpi), which has550* been interposed in the hierarchy between the API (MessageDigest)551* and its original parent (Object).552*/553554static class Delegate extends MessageDigest implements MessageDigestSpi2 {555556// The provider implementation (delegate)557private MessageDigestSpi digestSpi;558559// constructor560public Delegate(MessageDigestSpi digestSpi, String algorithm) {561super(algorithm);562this.digestSpi = digestSpi;563}564565/**566* Returns a clone if the delegate is cloneable.567*568* @return a clone if the delegate is cloneable.569*570* @exception CloneNotSupportedException if this is called on a571* delegate that does not support {@code Cloneable}.572*/573public Object clone() throws CloneNotSupportedException {574if (digestSpi instanceof Cloneable) {575MessageDigestSpi digestSpiClone =576(MessageDigestSpi)digestSpi.clone();577// Because 'algorithm', 'provider', and 'state' are private578// members of our supertype, we must perform a cast to579// access them.580MessageDigest that =581new Delegate(digestSpiClone,582((MessageDigest)this).algorithm);583that.provider = ((MessageDigest)this).provider;584that.state = ((MessageDigest)this).state;585return that;586} else {587throw new CloneNotSupportedException();588}589}590591protected int engineGetDigestLength() {592return digestSpi.engineGetDigestLength();593}594595protected void engineUpdate(byte input) {596digestSpi.engineUpdate(input);597}598599protected void engineUpdate(byte[] input, int offset, int len) {600digestSpi.engineUpdate(input, offset, len);601}602603protected void engineUpdate(ByteBuffer input) {604digestSpi.engineUpdate(input);605}606607public void engineUpdate(SecretKey key) throws InvalidKeyException {608if (digestSpi instanceof MessageDigestSpi2) {609((MessageDigestSpi2)digestSpi).engineUpdate(key);610} else {611throw new UnsupportedOperationException612("Digest does not support update of SecretKey object");613}614}615protected byte[] engineDigest() {616return digestSpi.engineDigest();617}618619protected int engineDigest(byte[] buf, int offset, int len)620throws DigestException {621return digestSpi.engineDigest(buf, offset, len);622}623624protected void engineReset() {625digestSpi.engineReset();626}627}628}629630631