001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.codec.digest;
019
020import java.io.BufferedInputStream;
021import java.io.File;
022import java.io.FileInputStream;
023import java.io.IOException;
024import java.io.InputStream;
025import java.nio.ByteBuffer;
026import java.security.MessageDigest;
027import java.security.NoSuchAlgorithmException;
028
029import org.apache.commons.codec.binary.Hex;
030import org.apache.commons.codec.binary.StringUtils;
031
032/**
033 * Operations to simplify common {@link java.security.MessageDigest} tasks.
034 * This class is immutable and thread-safe.
035 * However the MessageDigest instances it creates generally won't be.
036 * <p>
037 * The {@link MessageDigestAlgorithms} class provides constants for standard
038 * digest algorithms that can be used with the {@link #getDigest(String)} method
039 * and other methods that require the Digest algorithm name.
040 * <p>
041 * Note: the class has short-hand methods for all the algorithms present as standard in Java 6.
042 * This approach requires lots of methods for each algorithm, and quickly becomes unwieldy.
043 * The following code works with all algorithms:
044 * <pre>
045 * import static org.apache.commons.codec.digest.MessageDigestAlgorithms.SHA_224;
046 * ...
047 * byte [] digest = new DigestUtils(SHA_224).digest(dataToDigest);
048 * String hdigest = new DigestUtils(SHA_224).digestAsHex(new File("pom.xml"));
049 * </pre>
050 * @see MessageDigestAlgorithms
051 * @version $Id: DigestUtils.java 1811344 2017-10-06 15:19:57Z ggregory $
052 */
053public class DigestUtils {
054
055    private static final int STREAM_BUFFER_LENGTH = 1024;
056
057    /**
058     * Reads through a byte array and returns the digest for the data. Provided for symmetry with other methods.
059     *
060     * @param messageDigest
061     *            The MessageDigest to use (e.g. MD5)
062     * @param data
063     *            Data to digest
064     * @return the digest
065     * @since 1.11
066     */
067    public static byte[] digest(final MessageDigest messageDigest, final byte[] data) {
068        return messageDigest.digest(data);
069    }
070
071    /**
072     * Reads through a ByteBuffer and returns the digest for the data
073     *
074     * @param messageDigest
075     *            The MessageDigest to use (e.g. MD5)
076     * @param data
077     *            Data to digest
078     * @return the digest
079     *
080     * @since 1.11
081     */
082    public static byte[] digest(final MessageDigest messageDigest, final ByteBuffer data) {
083        messageDigest.update(data);
084        return messageDigest.digest();
085    }
086
087    /**
088     * Reads through a File and returns the digest for the data
089     *
090     * @param messageDigest
091     *            The MessageDigest to use (e.g. MD5)
092     * @param data
093     *            Data to digest
094     * @return the digest
095     * @throws IOException
096     *             On error reading from the stream
097     * @since 1.11
098     */
099    public static byte[] digest(final MessageDigest messageDigest, final File data) throws IOException {
100        return updateDigest(messageDigest, data).digest();
101    }
102
103    /**
104     * Reads through an InputStream and returns the digest for the data
105     *
106     * @param messageDigest
107     *            The MessageDigest to use (e.g. MD5)
108     * @param data
109     *            Data to digest
110     * @return the digest
111     * @throws IOException
112     *             On error reading from the stream
113     * @since 1.11 (was private)
114     */
115    public static byte[] digest(final MessageDigest messageDigest, final InputStream data) throws IOException {
116        return updateDigest(messageDigest, data).digest();
117    }
118
119    /**
120     * Returns a <code>MessageDigest</code> for the given <code>algorithm</code>.
121     *
122     * @param algorithm
123     *            the name of the algorithm requested. See <a
124     *            href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"
125     *            >Appendix A in the Java Cryptography Architecture Reference Guide</a> for information about standard
126     *            algorithm names.
127     * @return A digest instance.
128     * @see MessageDigest#getInstance(String)
129     * @throws IllegalArgumentException
130     *             when a {@link NoSuchAlgorithmException} is caught.
131     */
132    public static MessageDigest getDigest(final String algorithm) {
133        try {
134            return MessageDigest.getInstance(algorithm);
135        } catch (final NoSuchAlgorithmException e) {
136            throw new IllegalArgumentException(e);
137        }
138    }
139
140    /**
141     * Returns a <code>MessageDigest</code> for the given <code>algorithm</code> or a default if there is a problem
142     * getting the algorithm.
143     *
144     * @param algorithm
145     *            the name of the algorithm requested. See
146     *            <a href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA" >
147     *            Appendix A in the Java Cryptography Architecture Reference Guide</a> for information about standard
148     *            algorithm names.
149     * @param defaultMessageDigest
150     *            The default MessageDigest.
151     * @return A digest instance.
152     * @see MessageDigest#getInstance(String)
153     * @throws IllegalArgumentException
154     *             when a {@link NoSuchAlgorithmException} is caught.
155     * @since 1.11
156     */
157    public static MessageDigest getDigest(final String algorithm, final MessageDigest defaultMessageDigest) {
158        try {
159            return MessageDigest.getInstance(algorithm);
160        } catch (final Exception e) {
161            return defaultMessageDigest;
162        }
163    }
164
165    /**
166     * Returns an MD2 MessageDigest.
167     *
168     * @return An MD2 digest instance.
169     * @throws IllegalArgumentException
170     *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because MD2 is a
171     *             built-in algorithm
172     * @see MessageDigestAlgorithms#MD2
173     * @since 1.7
174     */
175    public static MessageDigest getMd2Digest() {
176        return getDigest(MessageDigestAlgorithms.MD2);
177    }
178
179    /**
180     * Returns an MD5 MessageDigest.
181     *
182     * @return An MD5 digest instance.
183     * @throws IllegalArgumentException
184     *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because MD5 is a
185     *             built-in algorithm
186     * @see MessageDigestAlgorithms#MD5
187     */
188    public static MessageDigest getMd5Digest() {
189        return getDigest(MessageDigestAlgorithms.MD5);
190    }
191
192    /**
193     * Returns an SHA-1 digest.
194     *
195     * @return An SHA-1 digest instance.
196     * @throws IllegalArgumentException
197     *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-1 is a
198     *             built-in algorithm
199     * @see MessageDigestAlgorithms#SHA_1
200     * @since 1.7
201     */
202    public static MessageDigest getSha1Digest() {
203        return getDigest(MessageDigestAlgorithms.SHA_1);
204    }
205
206    /**
207     * Returns an SHA-256 digest.
208     * <p>
209     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
210     * </p>
211     *
212     * @return An SHA-256 digest instance.
213     * @throws IllegalArgumentException
214     *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-256 is a
215     *             built-in algorithm
216     * @see MessageDigestAlgorithms#SHA_256
217     */
218    public static MessageDigest getSha256Digest() {
219        return getDigest(MessageDigestAlgorithms.SHA_256);
220    }
221
222    /**
223     * Returns an SHA-384 digest.
224     * <p>
225     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
226     * </p>
227     *
228     * @return An SHA-384 digest instance.
229     * @throws IllegalArgumentException
230     *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-384 is a
231     *             built-in algorithm
232     * @see MessageDigestAlgorithms#SHA_384
233     */
234    public static MessageDigest getSha384Digest() {
235        return getDigest(MessageDigestAlgorithms.SHA_384);
236    }
237
238    /**
239     * Returns an SHA-512 digest.
240     * <p>
241     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
242     * </p>
243     *
244     * @return An SHA-512 digest instance.
245     * @throws IllegalArgumentException
246     *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-512 is a
247     *             built-in algorithm
248     * @see MessageDigestAlgorithms#SHA_512
249     */
250    public static MessageDigest getSha512Digest() {
251        return getDigest(MessageDigestAlgorithms.SHA_512);
252    }
253
254    /**
255     * Returns an SHA-1 digest.
256     *
257     * @return An SHA-1 digest instance.
258     * @throws IllegalArgumentException
259     *             when a {@link NoSuchAlgorithmException} is caught
260     * @deprecated (1.11) Use {@link #getSha1Digest()}
261     */
262    @Deprecated
263    public static MessageDigest getShaDigest() {
264        return getSha1Digest();
265    }
266
267    /**
268     * Calculates the MD2 digest and returns the value as a 16 element <code>byte[]</code>.
269     *
270     * @param data
271     *            Data to digest
272     * @return MD2 digest
273     * @since 1.7
274     */
275    public static byte[] md2(final byte[] data) {
276        return getMd2Digest().digest(data);
277    }
278
279    /**
280     * Calculates the MD2 digest and returns the value as a 16 element <code>byte[]</code>.
281     *
282     * @param data
283     *            Data to digest
284     * @return MD2 digest
285     * @throws IOException
286     *             On error reading from the stream
287     * @since 1.7
288     */
289    public static byte[] md2(final InputStream data) throws IOException {
290        return digest(getMd2Digest(), data);
291    }
292
293    /**
294     * Calculates the MD2 digest and returns the value as a 16 element <code>byte[]</code>.
295     *
296     * @param data
297     *            Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
298     * @return MD2 digest
299     * @since 1.7
300     */
301    public static byte[] md2(final String data) {
302        return md2(StringUtils.getBytesUtf8(data));
303    }
304
305    /**
306     * Calculates the MD2 digest and returns the value as a 32 character hex string.
307     *
308     * @param data
309     *            Data to digest
310     * @return MD2 digest as a hex string
311     * @since 1.7
312     */
313    public static String md2Hex(final byte[] data) {
314        return Hex.encodeHexString(md2(data));
315    }
316
317    /**
318     * Calculates the MD2 digest and returns the value as a 32 character hex string.
319     *
320     * @param data
321     *            Data to digest
322     * @return MD2 digest as a hex string
323     * @throws IOException
324     *             On error reading from the stream
325     * @since 1.7
326     */
327    public static String md2Hex(final InputStream data) throws IOException {
328        return Hex.encodeHexString(md2(data));
329    }
330
331    /**
332     * Calculates the MD2 digest and returns the value as a 32 character hex string.
333     *
334     * @param data
335     *            Data to digest
336     * @return MD2 digest as a hex string
337     * @since 1.7
338     */
339    public static String md2Hex(final String data) {
340        return Hex.encodeHexString(md2(data));
341    }
342
343    /**
344     * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
345     *
346     * @param data
347     *            Data to digest
348     * @return MD5 digest
349     */
350    public static byte[] md5(final byte[] data) {
351        return getMd5Digest().digest(data);
352    }
353
354    /**
355     * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
356     *
357     * @param data
358     *            Data to digest
359     * @return MD5 digest
360     * @throws IOException
361     *             On error reading from the stream
362     * @since 1.4
363     */
364    public static byte[] md5(final InputStream data) throws IOException {
365        return digest(getMd5Digest(), data);
366    }
367
368    /**
369     * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
370     *
371     * @param data
372     *            Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
373     * @return MD5 digest
374     */
375    public static byte[] md5(final String data) {
376        return md5(StringUtils.getBytesUtf8(data));
377    }
378
379    /**
380     * Calculates the MD5 digest and returns the value as a 32 character hex string.
381     *
382     * @param data
383     *            Data to digest
384     * @return MD5 digest as a hex string
385     */
386    public static String md5Hex(final byte[] data) {
387        return Hex.encodeHexString(md5(data));
388    }
389
390    /**
391     * Calculates the MD5 digest and returns the value as a 32 character hex string.
392     *
393     * @param data
394     *            Data to digest
395     * @return MD5 digest as a hex string
396     * @throws IOException
397     *             On error reading from the stream
398     * @since 1.4
399     */
400    public static String md5Hex(final InputStream data) throws IOException {
401        return Hex.encodeHexString(md5(data));
402    }
403
404    /**
405     * Calculates the MD5 digest and returns the value as a 32 character hex string.
406     *
407     * @param data
408     *            Data to digest
409     * @return MD5 digest as a hex string
410     */
411    public static String md5Hex(final String data) {
412        return Hex.encodeHexString(md5(data));
413    }
414
415    /**
416     * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
417     *
418     * @param data
419     *            Data to digest
420     * @return SHA-1 digest
421     * @deprecated (1.11) Use {@link #sha1(byte[])}
422     */
423    @Deprecated
424    public static byte[] sha(final byte[] data) {
425        return sha1(data);
426    }
427
428    /**
429     * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
430     *
431     * @param data
432     *            Data to digest
433     * @return SHA-1 digest
434     * @throws IOException
435     *             On error reading from the stream
436     * @since 1.4
437     * @deprecated (1.11) Use {@link #sha1(InputStream)}
438     */
439    @Deprecated
440    public static byte[] sha(final InputStream data) throws IOException {
441        return sha1(data);
442    }
443
444    /**
445     * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
446     *
447     * @param data
448     *            Data to digest
449     * @return SHA-1 digest
450     * @deprecated (1.11) Use {@link #sha1(String)}
451     */
452    @Deprecated
453    public static byte[] sha(final String data) {
454        return sha1(data);
455    }
456
457    /**
458     * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
459     *
460     * @param data
461     *            Data to digest
462     * @return SHA-1 digest
463     * @since 1.7
464     */
465    public static byte[] sha1(final byte[] data) {
466        return getSha1Digest().digest(data);
467    }
468
469    /**
470     * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
471     *
472     * @param data
473     *            Data to digest
474     * @return SHA-1 digest
475     * @throws IOException
476     *             On error reading from the stream
477     * @since 1.7
478     */
479    public static byte[] sha1(final InputStream data) throws IOException {
480        return digest(getSha1Digest(), data);
481    }
482
483    /**
484     * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
485     *
486     * @param data
487     *            Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
488     * @return SHA-1 digest
489     */
490    public static byte[] sha1(final String data) {
491        return sha1(StringUtils.getBytesUtf8(data));
492    }
493
494    /**
495     * Calculates the SHA-1 digest and returns the value as a hex string.
496     *
497     * @param data
498     *            Data to digest
499     * @return SHA-1 digest as a hex string
500     * @since 1.7
501     */
502    public static String sha1Hex(final byte[] data) {
503        return Hex.encodeHexString(sha1(data));
504    }
505
506    /**
507     * Calculates the SHA-1 digest and returns the value as a hex string.
508     *
509     * @param data
510     *            Data to digest
511     * @return SHA-1 digest as a hex string
512     * @throws IOException
513     *             On error reading from the stream
514     * @since 1.7
515     */
516    public static String sha1Hex(final InputStream data) throws IOException {
517        return Hex.encodeHexString(sha1(data));
518    }
519
520    /**
521     * Calculates the SHA-1 digest and returns the value as a hex string.
522     *
523     * @param data
524     *            Data to digest
525     * @return SHA-1 digest as a hex string
526     * @since 1.7
527     */
528    public static String sha1Hex(final String data) {
529        return Hex.encodeHexString(sha1(data));
530    }
531
532    /**
533     * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
534     * <p>
535     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
536     * </p>
537     *
538     * @param data
539     *            Data to digest
540     * @return SHA-256 digest
541     * @since 1.4
542     */
543    public static byte[] sha256(final byte[] data) {
544        return getSha256Digest().digest(data);
545    }
546
547    /**
548     * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
549     * <p>
550     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
551     * </p>
552     *
553     * @param data
554     *            Data to digest
555     * @return SHA-256 digest
556     * @throws IOException
557     *             On error reading from the stream
558     * @since 1.4
559     */
560    public static byte[] sha256(final InputStream data) throws IOException {
561        return digest(getSha256Digest(), data);
562    }
563
564    /**
565     * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
566     * <p>
567     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
568     * </p>
569     *
570     * @param data
571     *            Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
572     * @return SHA-256 digest
573     * @since 1.4
574     */
575    public static byte[] sha256(final String data) {
576        return sha256(StringUtils.getBytesUtf8(data));
577    }
578
579    /**
580     * Calculates the SHA-256 digest and returns the value as a hex string.
581     * <p>
582     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
583     * </p>
584     *
585     * @param data
586     *            Data to digest
587     * @return SHA-256 digest as a hex string
588     * @since 1.4
589     */
590    public static String sha256Hex(final byte[] data) {
591        return Hex.encodeHexString(sha256(data));
592    }
593
594    /**
595     * Calculates the SHA-256 digest and returns the value as a hex string.
596     * <p>
597     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
598     * </p>
599     *
600     * @param data
601     *            Data to digest
602     * @return SHA-256 digest as a hex string
603     * @throws IOException
604     *             On error reading from the stream
605     * @since 1.4
606     */
607    public static String sha256Hex(final InputStream data) throws IOException {
608        return Hex.encodeHexString(sha256(data));
609    }
610
611    /**
612     * Calculates the SHA-256 digest and returns the value as a hex string.
613     * <p>
614     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
615     * </p>
616     *
617     * @param data
618     *            Data to digest
619     * @return SHA-256 digest as a hex string
620     * @since 1.4
621     */
622    public static String sha256Hex(final String data) {
623        return Hex.encodeHexString(sha256(data));
624    }
625
626    /**
627     * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
628     * <p>
629     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
630     * </p>
631     *
632     * @param data
633     *            Data to digest
634     * @return SHA-384 digest
635     * @since 1.4
636     */
637    public static byte[] sha384(final byte[] data) {
638        return getSha384Digest().digest(data);
639    }
640
641    /**
642     * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
643     * <p>
644     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
645     * </p>
646     *
647     * @param data
648     *            Data to digest
649     * @return SHA-384 digest
650     * @throws IOException
651     *             On error reading from the stream
652     * @since 1.4
653     */
654    public static byte[] sha384(final InputStream data) throws IOException {
655        return digest(getSha384Digest(), data);
656    }
657
658    /**
659     * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
660     * <p>
661     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
662     * </p>
663     *
664     * @param data
665     *            Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
666     * @return SHA-384 digest
667     * @since 1.4
668     */
669    public static byte[] sha384(final String data) {
670        return sha384(StringUtils.getBytesUtf8(data));
671    }
672
673    /**
674     * Calculates the SHA-384 digest and returns the value as a hex string.
675     * <p>
676     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
677     * </p>
678     *
679     * @param data
680     *            Data to digest
681     * @return SHA-384 digest as a hex string
682     * @since 1.4
683     */
684    public static String sha384Hex(final byte[] data) {
685        return Hex.encodeHexString(sha384(data));
686    }
687
688    /**
689     * Calculates the SHA-384 digest and returns the value as a hex string.
690     * <p>
691     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
692     * </p>
693     *
694     * @param data
695     *            Data to digest
696     * @return SHA-384 digest as a hex string
697     * @throws IOException
698     *             On error reading from the stream
699     * @since 1.4
700     */
701    public static String sha384Hex(final InputStream data) throws IOException {
702        return Hex.encodeHexString(sha384(data));
703    }
704
705    /**
706     * Calculates the SHA-384 digest and returns the value as a hex string.
707     * <p>
708     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
709     * </p>
710     *
711     * @param data
712     *            Data to digest
713     * @return SHA-384 digest as a hex string
714     * @since 1.4
715     */
716    public static String sha384Hex(final String data) {
717        return Hex.encodeHexString(sha384(data));
718    }
719
720    /**
721     * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
722     * <p>
723     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
724     * </p>
725     *
726     * @param data
727     *            Data to digest
728     * @return SHA-512 digest
729     * @since 1.4
730     */
731    public static byte[] sha512(final byte[] data) {
732        return getSha512Digest().digest(data);
733    }
734
735    /**
736     * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
737     * <p>
738     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
739     * </p>
740     *
741     * @param data
742     *            Data to digest
743     * @return SHA-512 digest
744     * @throws IOException
745     *             On error reading from the stream
746     * @since 1.4
747     */
748    public static byte[] sha512(final InputStream data) throws IOException {
749        return digest(getSha512Digest(), data);
750    }
751
752    /**
753     * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
754     * <p>
755     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
756     * </p>
757     *
758     * @param data
759     *            Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
760     * @return SHA-512 digest
761     * @since 1.4
762     */
763    public static byte[] sha512(final String data) {
764        return sha512(StringUtils.getBytesUtf8(data));
765    }
766
767    /**
768     * Calculates the SHA-512 digest and returns the value as a hex string.
769     * <p>
770     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
771     * </p>
772     *
773     * @param data
774     *            Data to digest
775     * @return SHA-512 digest as a hex string
776     * @since 1.4
777     */
778    public static String sha512Hex(final byte[] data) {
779        return Hex.encodeHexString(sha512(data));
780    }
781
782    /**
783     * Calculates the SHA-512 digest and returns the value as a hex string.
784     * <p>
785     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
786     * </p>
787     *
788     * @param data
789     *            Data to digest
790     * @return SHA-512 digest as a hex string
791     * @throws IOException
792     *             On error reading from the stream
793     * @since 1.4
794     */
795    public static String sha512Hex(final InputStream data) throws IOException {
796        return Hex.encodeHexString(sha512(data));
797    }
798
799    /**
800     * Calculates the SHA-512 digest and returns the value as a hex string.
801     * <p>
802     * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
803     * </p>
804     *
805     * @param data
806     *            Data to digest
807     * @return SHA-512 digest as a hex string
808     * @since 1.4
809     */
810    public static String sha512Hex(final String data) {
811        return Hex.encodeHexString(sha512(data));
812    }
813
814    /**
815     * Calculates the SHA-1 digest and returns the value as a hex string.
816     *
817     * @param data
818     *            Data to digest
819     * @return SHA-1 digest as a hex string
820     * @deprecated (1.11) Use {@link #sha1Hex(byte[])}
821     */
822    @Deprecated
823    public static String shaHex(final byte[] data) {
824        return sha1Hex(data);
825    }
826
827    /**
828     * Calculates the SHA-1 digest and returns the value as a hex string.
829     *
830     * @param data
831     *            Data to digest
832     * @return SHA-1 digest as a hex string
833     * @throws IOException
834     *             On error reading from the stream
835     * @since 1.4
836     * @deprecated (1.11) Use {@link #sha1Hex(InputStream)}
837     */
838    @Deprecated
839    public static String shaHex(final InputStream data) throws IOException {
840        return sha1Hex(data);
841    }
842
843    /**
844     * Calculates the SHA-1 digest and returns the value as a hex string.
845     *
846     * @param data
847     *            Data to digest
848     * @return SHA-1 digest as a hex string
849     * @deprecated (1.11) Use {@link #sha1Hex(String)}
850     */
851    @Deprecated
852    public static String shaHex(final String data) {
853        return sha1Hex(data);
854    }
855
856    /**
857     * Updates the given {@link MessageDigest}.
858     *
859     * @param messageDigest
860     *            the {@link MessageDigest} to update
861     * @param valueToDigest
862     *            the value to update the {@link MessageDigest} with
863     * @return the updated {@link MessageDigest}
864     * @since 1.7
865     */
866    public static MessageDigest updateDigest(final MessageDigest messageDigest, final byte[] valueToDigest) {
867        messageDigest.update(valueToDigest);
868        return messageDigest;
869    }
870
871    /**
872     * Updates the given {@link MessageDigest}.
873     *
874     * @param messageDigest
875     *            the {@link MessageDigest} to update
876     * @param valueToDigest
877     *            the value to update the {@link MessageDigest} with
878     * @return the updated {@link MessageDigest}
879     * @since 1.11
880     */
881    public static MessageDigest updateDigest(final MessageDigest messageDigest, final ByteBuffer valueToDigest) {
882        messageDigest.update(valueToDigest);
883        return messageDigest;
884    }
885
886    /**
887     * Reads through a File and updates the digest for the data
888     *
889     * @param digest
890     *            The MessageDigest to use (e.g. MD5)
891     * @param data
892     *            Data to digest
893     * @return the digest
894     * @throws IOException
895     *             On error reading from the stream
896     * @since 1.11
897     */
898    public static MessageDigest updateDigest(final MessageDigest digest, final File data) throws IOException {
899        final BufferedInputStream stream = new BufferedInputStream(new FileInputStream(data));
900        try {
901            return updateDigest(digest, stream);
902        } finally {
903            stream.close();
904        }
905    }
906
907    /**
908     * Reads through an InputStream and updates the digest for the data
909     *
910     * @param digest
911     *            The MessageDigest to use (e.g. MD5)
912     * @param data
913     *            Data to digest
914     * @return the digest
915     * @throws IOException
916     *             On error reading from the stream
917     * @since 1.8
918     */
919    public static MessageDigest updateDigest(final MessageDigest digest, final InputStream data) throws IOException {
920        final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
921        int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
922
923        while (read > -1) {
924            digest.update(buffer, 0, read);
925            read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
926        }
927
928        return digest;
929    }
930
931    /**
932     * Updates the given {@link MessageDigest} from a String (converted to bytes using UTF-8).
933     * <p>
934     * To update the digest using a different charset for the conversion,
935     * convert the String to a byte array using
936     * {@link String#getBytes(java.nio.charset.Charset)} and pass that
937     * to the {@link DigestUtils#updateDigest(MessageDigest, byte[])} method
938     *
939     * @param messageDigest
940     *            the {@link MessageDigest} to update
941     * @param valueToDigest
942     *            the value to update the {@link MessageDigest} with;
943     *            converted to bytes using {@link StringUtils#getBytesUtf8(String)}
944     * @return the updated {@link MessageDigest}
945     * @since 1.7
946     */
947    public static MessageDigest updateDigest(final MessageDigest messageDigest, final String valueToDigest) {
948        messageDigest.update(StringUtils.getBytesUtf8(valueToDigest));
949        return messageDigest;
950    }
951
952    /**
953     * Test whether the algorithm is supported.
954     * @param messageDigestAlgorithm the algorithm name
955     * @return {@code true} if the algorithm can be found
956     * @since 1.11
957     */
958    public static boolean isAvailable(final String messageDigestAlgorithm) {
959        return getDigest(messageDigestAlgorithm, null) != null;
960    }
961
962    private final MessageDigest messageDigest;
963
964   /**
965    * Preserves binary compatibity only.
966    * As for previous versions does not provide useful behaviour
967    * @deprecated since 1.11; only useful to preserve binary compatibility
968    */
969   @Deprecated
970    public DigestUtils() {
971        this.messageDigest = null;
972    }
973
974    /**
975     * Creates an instance using the provided {@link MessageDigest} parameter.
976     *
977     * This can then be used to create digests using methods such as
978     * {@link #digest(byte[])} and {@link #digestAsHex(File)}.
979     *
980     * @param digest the {@link MessageDigest} to use
981     * @since 1.11
982     */
983    public DigestUtils(final MessageDigest digest) {
984        this.messageDigest = digest;
985    }
986
987    /**
988     * Creates an instance using the provided {@link MessageDigest} parameter.
989     *
990     * This can then be used to create digests using methods such as
991     * {@link #digest(byte[])} and {@link #digestAsHex(File)}.
992     *
993     * @param name the name of the {@link MessageDigest} to use
994     * @see #getDigest(String)
995     * @throws IllegalArgumentException
996     *             when a {@link NoSuchAlgorithmException} is caught.
997     * @since 1.11
998     */
999    public DigestUtils(final String name) {
1000        this(getDigest(name));
1001    }
1002
1003    /**
1004     * Returns the message digest instance.
1005     * @return the message digest instance
1006     * @since 1.11
1007     */
1008    public MessageDigest getMessageDigest() {
1009        return messageDigest;
1010    }
1011
1012    /**
1013     * Reads through a byte array and returns the digest for the data.
1014     *
1015     * @param data
1016     *            Data to digest
1017     * @return the digest
1018     * @since 1.11
1019     */
1020    public byte[] digest(final byte[] data) {
1021        return updateDigest(messageDigest, data).digest();
1022    }
1023
1024    /**
1025     * Reads through a byte array and returns the digest for the data.
1026     *
1027     * @param data
1028     *            Data to digest treated as UTF-8 string
1029     * @return the digest
1030     * @since 1.11
1031     */
1032    public byte[] digest(final String data) {
1033        return updateDigest(messageDigest, data).digest();
1034    }
1035
1036    /**
1037     * Reads through a ByteBuffer and returns the digest for the data
1038     *
1039     * @param data
1040     *            Data to digest
1041     * @return the digest
1042     *
1043     * @since 1.11
1044     */
1045    public byte[] digest(final ByteBuffer data) {
1046        return updateDigest(messageDigest, data).digest();
1047    }
1048
1049    /**
1050     * Reads through a File and returns the digest for the data
1051     *
1052     * @param data
1053     *            Data to digest
1054     * @return the digest
1055     * @throws IOException
1056     *             On error reading from the stream
1057     * @since 1.11
1058     */
1059    public byte[] digest(final File data) throws IOException {
1060        return updateDigest(messageDigest, data).digest();
1061    }
1062
1063    /**
1064     * Reads through an InputStream and returns the digest for the data
1065     *
1066     * @param data
1067     *            Data to digest
1068     * @return the digest
1069     * @throws IOException
1070     *             On error reading from the stream
1071     * @since 1.11
1072     */
1073    public byte[] digest(final InputStream data) throws IOException {
1074        return updateDigest(messageDigest, data).digest();
1075    }
1076
1077    /**
1078     * Reads through a byte array and returns the digest for the data.
1079     *
1080     * @param data
1081     *            Data to digest
1082     * @return the digest as a hex string
1083     * @since 1.11
1084     */
1085    public String digestAsHex(final byte[] data) {
1086        return Hex.encodeHexString(digest(data));
1087    }
1088
1089    /**
1090     * Reads through a byte array and returns the digest for the data.
1091     *
1092     * @param data
1093     *            Data to digest treated as UTF-8 string
1094     * @return the digest as a hex string
1095     * @since 1.11
1096     */
1097    public String digestAsHex(final String data) {
1098        return Hex.encodeHexString(digest(data));
1099    }
1100
1101    /**
1102     * Reads through a ByteBuffer and returns the digest for the data
1103     *
1104     * @param data
1105     *            Data to digest
1106     * @return the digest as a hex string
1107     *
1108     * @since 1.11
1109     */
1110    public String digestAsHex(final ByteBuffer data) {
1111        return Hex.encodeHexString(digest(data));
1112    }
1113
1114    /**
1115     * Reads through a File and returns the digest for the data
1116     *
1117     * @param data
1118     *            Data to digest
1119     * @return the digest as a hex string
1120     * @throws IOException
1121     *             On error reading from the stream
1122     * @since 1.11
1123     */
1124    public String digestAsHex(final File data) throws IOException {
1125        return Hex.encodeHexString(digest(data));
1126    }
1127
1128    /**
1129     * Reads through an InputStream and returns the digest for the data
1130     *
1131     * @param data
1132     *            Data to digest
1133     * @return the digest as a hex string
1134     * @throws IOException
1135     *             On error reading from the stream
1136     * @since 1.11
1137     */
1138    public String digestAsHex(final InputStream data) throws IOException {
1139        return Hex.encodeHexString(digest(data));
1140    }
1141
1142}