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    
018    package org.apache.commons.codec.digest;
019    
020    import java.io.IOException;
021    import java.io.InputStream;
022    import java.security.MessageDigest;
023    import java.security.NoSuchAlgorithmException;
024    
025    import org.apache.commons.codec.binary.Hex;
026    import org.apache.commons.codec.binary.StringUtils;
027    
028    /**
029     * Operations to simplify common {@link java.security.MessageDigest} tasks. This class is thread safe.
030     *
031     * @version $Id: DigestUtils.html 889935 2013-12-11 05:05:13Z ggregory $
032     */
033    public class DigestUtils {
034    
035        private static final int STREAM_BUFFER_LENGTH = 1024;
036    
037        /**
038         * Read through an InputStream and returns the digest for the data
039         *
040         * @param digest
041         *            The MessageDigest to use (e.g. MD5)
042         * @param data
043         *            Data to digest
044         * @return MD5 digest
045         * @throws IOException
046         *             On error reading from the stream
047         */
048        private static byte[] digest(MessageDigest digest, InputStream data) throws IOException {
049            byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
050            int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
051    
052            while (read > -1) {
053                digest.update(buffer, 0, read);
054                read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
055            }
056    
057            return digest.digest();
058        }
059    
060        /**
061         * Calls {@link StringUtils#getBytesUtf8(String)}
062         *
063         * @param data
064         *            the String to encode
065         * @return encoded bytes
066         */
067        private static byte[] getBytesUtf8(String data) {
068            return StringUtils.getBytesUtf8(data);
069        }
070    
071        /**
072         * Returns a <code>MessageDigest</code> for the given <code>algorithm</code>.
073         *
074         * @param algorithm
075         *            the name of the algorithm requested. See <a
076         *            href="http://java.sun.com/j2se/1.3/docs/guide/security/CryptoSpec.html#AppA">Appendix A in the Java
077         *            Cryptography Architecture API Specification & Reference</a> for information about standard algorithm
078         *            names.
079         * @return An MD5 digest instance.
080         * @see MessageDigest#getInstance(String)
081         * @throws IllegalArgumentException
082         *             when a {@link NoSuchAlgorithmException} is caught.
083         */
084        public static MessageDigest getDigest(String algorithm) {
085            try {
086                return MessageDigest.getInstance(algorithm);
087            } catch (NoSuchAlgorithmException e) {
088                throw new IllegalArgumentException(e);
089            }
090        }
091    
092        /**
093         * Returns an MD2 MessageDigest.
094         *
095         * @return An MD2 digest instance.
096         * @throws IllegalArgumentException
097         *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because MD2 is a
098         *             built-in algorithm
099         * @see MessageDigestAlgorithms#MD2
100         * @since 1.7
101         */
102        public static MessageDigest getMd2Digest() {
103            return getDigest(MessageDigestAlgorithms.MD2);
104        }
105    
106        /**
107         * Returns an MD5 MessageDigest.
108         *
109         * @return An MD5 digest instance.
110         * @throws IllegalArgumentException
111         *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because MD5 is a
112         *             built-in algorithm
113         * @see MessageDigestAlgorithms#MD5
114         */
115        public static MessageDigest getMd5Digest() {
116            return getDigest(MessageDigestAlgorithms.MD5);
117        }
118    
119        /**
120         * Returns an SHA-1 digest.
121         *
122         * @return An SHA-1 digest instance.
123         * @throws IllegalArgumentException
124         *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-1 is a
125         *             built-in algorithm
126         * @see MessageDigestAlgorithms#SHA_1
127         * @since 1.7
128         */
129        public static MessageDigest getSha1Digest() {
130            return getDigest(MessageDigestAlgorithms.SHA_1);
131        }
132    
133        /**
134         * Returns an SHA-256 digest.
135         * <p>
136         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
137         * </p>
138         *
139         * @return An SHA-256 digest instance.
140         * @throws IllegalArgumentException
141         *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-256 is a
142         *             built-in algorithm
143         * @see MessageDigestAlgorithms#SHA_256
144         */
145        public static MessageDigest getSha256Digest() {
146            return getDigest(MessageDigestAlgorithms.SHA_256);
147        }
148    
149        /**
150         * Returns an SHA-384 digest.
151         * <p>
152         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
153         * </p>
154         *
155         * @return An SHA-384 digest instance.
156         * @throws IllegalArgumentException
157         *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-384 is a
158         *             built-in algorithm
159         * @see MessageDigestAlgorithms#SHA_384
160         */
161        public static MessageDigest getSha384Digest() {
162            return getDigest(MessageDigestAlgorithms.SHA_384);
163        }
164    
165        /**
166         * Returns an SHA-512 digest.
167         * <p>
168         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
169         * </p>
170         *
171         * @return An SHA-512 digest instance.
172         * @throws IllegalArgumentException
173         *             when a {@link NoSuchAlgorithmException} is caught, which should never happen because SHA-512 is a
174         *             built-in algorithm
175         * @see MessageDigestAlgorithms#SHA_512
176         */
177        public static MessageDigest getSha512Digest() {
178            return getDigest(MessageDigestAlgorithms.SHA_512);
179        }
180    
181        /**
182         * Returns an SHA-1 digest.
183         *
184         * @return An SHA-1 digest instance.
185         * @throws IllegalArgumentException
186         *             when a {@link NoSuchAlgorithmException} is caught
187         * @deprecated Use {@link #getSha1Digest()}
188         */
189        @Deprecated
190        public static MessageDigest getShaDigest() {
191            return getSha1Digest();
192        }
193    
194        /**
195         * Calculates the MD2 digest and returns the value as a 16 element <code>byte[]</code>.
196         *
197         * @param data
198         *            Data to digest
199         * @return MD2 digest
200         * @since 1.7
201         */
202        public static byte[] md2(byte[] data) {
203            return getMd2Digest().digest(data);
204        }
205    
206        /**
207         * Calculates the MD2 digest and returns the value as a 16 element <code>byte[]</code>.
208         *
209         * @param data
210         *            Data to digest
211         * @return MD2 digest
212         * @throws IOException
213         *             On error reading from the stream
214         * @since 1.7
215         */
216        public static byte[] md2(InputStream data) throws IOException {
217            return digest(getMd2Digest(), data);
218        }
219    
220        /**
221         * Calculates the MD2 digest and returns the value as a 16 element <code>byte[]</code>.
222         *
223         * @param data
224         *            Data to digest
225         * @return MD2 digest
226         * @since 1.7
227         */
228        public static byte[] md2(String data) {
229            return md2(getBytesUtf8(data));
230        }
231    
232        /**
233         * Calculates the MD2 digest and returns the value as a 32 character hex string.
234         *
235         * @param data
236         *            Data to digest
237         * @return MD2 digest as a hex string
238         * @since 1.7
239         */
240        public static String md2Hex(byte[] data) {
241            return Hex.encodeHexString(md2(data));
242        }
243    
244        /**
245         * Calculates the MD2 digest and returns the value as a 32 character hex string.
246         *
247         * @param data
248         *            Data to digest
249         * @return MD2 digest as a hex string
250         * @throws IOException
251         *             On error reading from the stream
252         * @since 1.7
253         */
254        public static String md2Hex(InputStream data) throws IOException {
255            return Hex.encodeHexString(md2(data));
256        }
257    
258        /**
259         * Calculates the MD2 digest and returns the value as a 32 character hex string.
260         *
261         * @param data
262         *            Data to digest
263         * @return MD2 digest as a hex string
264         * @since 1.7
265         */
266        public static String md2Hex(String data) {
267            return Hex.encodeHexString(md2(data));
268        }
269    
270        /**
271         * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
272         *
273         * @param data
274         *            Data to digest
275         * @return MD5 digest
276         */
277        public static byte[] md5(byte[] data) {
278            return getMd5Digest().digest(data);
279        }
280    
281        /**
282         * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
283         *
284         * @param data
285         *            Data to digest
286         * @return MD5 digest
287         * @throws IOException
288         *             On error reading from the stream
289         * @since 1.4
290         */
291        public static byte[] md5(InputStream data) throws IOException {
292            return digest(getMd5Digest(), data);
293        }
294    
295        /**
296         * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
297         *
298         * @param data
299         *            Data to digest
300         * @return MD5 digest
301         */
302        public static byte[] md5(String data) {
303            return md5(getBytesUtf8(data));
304        }
305    
306        /**
307         * Calculates the MD5 digest and returns the value as a 32 character hex string.
308         *
309         * @param data
310         *            Data to digest
311         * @return MD5 digest as a hex string
312         */
313        public static String md5Hex(byte[] data) {
314            return Hex.encodeHexString(md5(data));
315        }
316    
317        /**
318         * Calculates the MD5 digest and returns the value as a 32 character hex string.
319         *
320         * @param data
321         *            Data to digest
322         * @return MD5 digest as a hex string
323         * @throws IOException
324         *             On error reading from the stream
325         * @since 1.4
326         */
327        public static String md5Hex(InputStream data) throws IOException {
328            return Hex.encodeHexString(md5(data));
329        }
330    
331        /**
332         * Calculates the MD5 digest and returns the value as a 32 character hex string.
333         *
334         * @param data
335         *            Data to digest
336         * @return MD5 digest as a hex string
337         */
338        public static String md5Hex(String data) {
339            return Hex.encodeHexString(md5(data));
340        }
341    
342        /**
343         * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
344         *
345         * @param data
346         *            Data to digest
347         * @return SHA-1 digest
348         * @deprecated Use {@link #sha1(byte[])}
349         */
350        @Deprecated
351        public static byte[] sha(byte[] data) {
352            return sha1(data);
353        }
354    
355        /**
356         * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
357         *
358         * @param data
359         *            Data to digest
360         * @return SHA-1 digest
361         * @throws IOException
362         *             On error reading from the stream
363         * @since 1.4
364         * @deprecated Use {@link #sha1(InputStream)}
365         */
366        @Deprecated
367        public static byte[] sha(InputStream data) throws IOException {
368            return sha1(data);
369        }
370    
371        /**
372         * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
373         *
374         * @param data
375         *            Data to digest
376         * @return SHA-1 digest
377         * @deprecated Use {@link #sha1(String)}
378         */
379        @Deprecated
380        public static byte[] sha(String data) {
381            return sha1(data);
382        }
383    
384        /**
385         * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
386         *
387         * @param data
388         *            Data to digest
389         * @return SHA-1 digest
390         * @since 1.7
391         */
392        public static byte[] sha1(byte[] data) {
393            return getSha1Digest().digest(data);
394        }
395    
396        /**
397         * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
398         *
399         * @param data
400         *            Data to digest
401         * @return SHA-1 digest
402         * @throws IOException
403         *             On error reading from the stream
404         * @since 1.7
405         */
406        public static byte[] sha1(InputStream data) throws IOException {
407            return digest(getSha1Digest(), data);
408        }
409    
410        /**
411         * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
412         *
413         * @param data
414         *            Data to digest
415         * @return SHA-1 digest
416         */
417        public static byte[] sha1(String data) {
418            return sha1(getBytesUtf8(data));
419        }
420    
421        /**
422         * Calculates the SHA-1 digest and returns the value as a hex string.
423         *
424         * @param data
425         *            Data to digest
426         * @return SHA-1 digest as a hex string
427         * @since 1.7
428         */
429        public static String sha1Hex(byte[] data) {
430            return Hex.encodeHexString(sha1(data));
431        }
432    
433        /**
434         * Calculates the SHA-1 digest and returns the value as a hex string.
435         *
436         * @param data
437         *            Data to digest
438         * @return SHA-1 digest as a hex string
439         * @throws IOException
440         *             On error reading from the stream
441         * @since 1.7
442         */
443        public static String sha1Hex(InputStream data) throws IOException {
444            return Hex.encodeHexString(sha1(data));
445        }
446    
447        /**
448         * Calculates the SHA-1 digest and returns the value as a hex string.
449         *
450         * @param data
451         *            Data to digest
452         * @return SHA-1 digest as a hex string
453         * @since 1.7
454         */
455        public static String sha1Hex(String data) {
456            return Hex.encodeHexString(sha1(data));
457        }
458    
459        /**
460         * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
461         * <p>
462         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
463         * </p>
464         *
465         * @param data
466         *            Data to digest
467         * @return SHA-256 digest
468         * @since 1.4
469         */
470        public static byte[] sha256(byte[] data) {
471            return getSha256Digest().digest(data);
472        }
473    
474        /**
475         * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
476         * <p>
477         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
478         * </p>
479         *
480         * @param data
481         *            Data to digest
482         * @return SHA-256 digest
483         * @throws IOException
484         *             On error reading from the stream
485         * @since 1.4
486         */
487        public static byte[] sha256(InputStream data) throws IOException {
488            return digest(getSha256Digest(), data);
489        }
490    
491        /**
492         * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
493         * <p>
494         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
495         * </p>
496         *
497         * @param data
498         *            Data to digest
499         * @return SHA-256 digest
500         * @since 1.4
501         */
502        public static byte[] sha256(String data) {
503            return sha256(getBytesUtf8(data));
504        }
505    
506        /**
507         * Calculates the SHA-256 digest and returns the value as a hex string.
508         * <p>
509         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
510         * </p>
511         *
512         * @param data
513         *            Data to digest
514         * @return SHA-256 digest as a hex string
515         * @since 1.4
516         */
517        public static String sha256Hex(byte[] data) {
518            return Hex.encodeHexString(sha256(data));
519        }
520    
521        /**
522         * Calculates the SHA-256 digest and returns the value as a hex string.
523         * <p>
524         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
525         * </p>
526         *
527         * @param data
528         *            Data to digest
529         * @return SHA-256 digest as a hex string
530         * @throws IOException
531         *             On error reading from the stream
532         * @since 1.4
533         */
534        public static String sha256Hex(InputStream data) throws IOException {
535            return Hex.encodeHexString(sha256(data));
536        }
537    
538        /**
539         * Calculates the SHA-256 digest and returns the value as a hex string.
540         * <p>
541         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
542         * </p>
543         *
544         * @param data
545         *            Data to digest
546         * @return SHA-256 digest as a hex string
547         * @since 1.4
548         */
549        public static String sha256Hex(String data) {
550            return Hex.encodeHexString(sha256(data));
551        }
552    
553        /**
554         * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
555         * <p>
556         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
557         * </p>
558         *
559         * @param data
560         *            Data to digest
561         * @return SHA-384 digest
562         * @since 1.4
563         */
564        public static byte[] sha384(byte[] data) {
565            return getSha384Digest().digest(data);
566        }
567    
568        /**
569         * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
570         * <p>
571         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
572         * </p>
573         *
574         * @param data
575         *            Data to digest
576         * @return SHA-384 digest
577         * @throws IOException
578         *             On error reading from the stream
579         * @since 1.4
580         */
581        public static byte[] sha384(InputStream data) throws IOException {
582            return digest(getSha384Digest(), data);
583        }
584    
585        /**
586         * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
587         * <p>
588         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
589         * </p>
590         *
591         * @param data
592         *            Data to digest
593         * @return SHA-384 digest
594         * @since 1.4
595         */
596        public static byte[] sha384(String data) {
597            return sha384(getBytesUtf8(data));
598        }
599    
600        /**
601         * Calculates the SHA-384 digest and returns the value as a hex string.
602         * <p>
603         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
604         * </p>
605         *
606         * @param data
607         *            Data to digest
608         * @return SHA-384 digest as a hex string
609         * @since 1.4
610         */
611        public static String sha384Hex(byte[] data) {
612            return Hex.encodeHexString(sha384(data));
613        }
614    
615        /**
616         * Calculates the SHA-384 digest and returns the value as a hex string.
617         * <p>
618         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
619         * </p>
620         *
621         * @param data
622         *            Data to digest
623         * @return SHA-384 digest as a hex string
624         * @throws IOException
625         *             On error reading from the stream
626         * @since 1.4
627         */
628        public static String sha384Hex(InputStream data) throws IOException {
629            return Hex.encodeHexString(sha384(data));
630        }
631    
632        /**
633         * Calculates the SHA-384 digest and returns the value as a hex string.
634         * <p>
635         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
636         * </p>
637         *
638         * @param data
639         *            Data to digest
640         * @return SHA-384 digest as a hex string
641         * @since 1.4
642         */
643        public static String sha384Hex(String data) {
644            return Hex.encodeHexString(sha384(data));
645        }
646    
647        /**
648         * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
649         * <p>
650         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
651         * </p>
652         *
653         * @param data
654         *            Data to digest
655         * @return SHA-512 digest
656         * @since 1.4
657         */
658        public static byte[] sha512(byte[] data) {
659            return getSha512Digest().digest(data);
660        }
661    
662        /**
663         * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
664         * <p>
665         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
666         * </p>
667         *
668         * @param data
669         *            Data to digest
670         * @return SHA-512 digest
671         * @throws IOException
672         *             On error reading from the stream
673         * @since 1.4
674         */
675        public static byte[] sha512(InputStream data) throws IOException {
676            return digest(getSha512Digest(), data);
677        }
678    
679        /**
680         * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
681         * <p>
682         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
683         * </p>
684         *
685         * @param data
686         *            Data to digest
687         * @return SHA-512 digest
688         * @since 1.4
689         */
690        public static byte[] sha512(String data) {
691            return sha512(getBytesUtf8(data));
692        }
693    
694        /**
695         * Calculates the SHA-512 digest and returns the value as a hex string.
696         * <p>
697         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
698         * </p>
699         *
700         * @param data
701         *            Data to digest
702         * @return SHA-512 digest as a hex string
703         * @since 1.4
704         */
705        public static String sha512Hex(byte[] data) {
706            return Hex.encodeHexString(sha512(data));
707        }
708    
709        /**
710         * Calculates the SHA-512 digest and returns the value as a hex string.
711         * <p>
712         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
713         * </p>
714         *
715         * @param data
716         *            Data to digest
717         * @return SHA-512 digest as a hex string
718         * @throws IOException
719         *             On error reading from the stream
720         * @since 1.4
721         */
722        public static String sha512Hex(InputStream data) throws IOException {
723            return Hex.encodeHexString(sha512(data));
724        }
725    
726        /**
727         * Calculates the SHA-512 digest and returns the value as a hex string.
728         * <p>
729         * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
730         * </p>
731         *
732         * @param data
733         *            Data to digest
734         * @return SHA-512 digest as a hex string
735         * @since 1.4
736         */
737        public static String sha512Hex(String data) {
738            return Hex.encodeHexString(sha512(data));
739        }
740    
741        /**
742         * Calculates the SHA-1 digest and returns the value as a hex string.
743         *
744         * @param data
745         *            Data to digest
746         * @return SHA-1 digest as a hex string
747         * @deprecated Use {@link #sha1Hex(byte[])}
748         */
749        @Deprecated
750        public static String shaHex(byte[] data) {
751            return sha1Hex(data);
752        }
753    
754        /**
755         * Calculates the SHA-1 digest and returns the value as a hex string.
756         *
757         * @param data
758         *            Data to digest
759         * @return SHA-1 digest as a hex string
760         * @throws IOException
761         *             On error reading from the stream
762         * @since 1.4
763         * @deprecated Use {@link #sha1Hex(InputStream)}
764         */
765        @Deprecated
766        public static String shaHex(InputStream data) throws IOException {
767            return sha1Hex(data);
768        }
769    
770        /**
771         * Calculates the SHA-1 digest and returns the value as a hex string.
772         *
773         * @param data
774         *            Data to digest
775         * @return SHA-1 digest as a hex string
776         * @deprecated Use {@link #sha1Hex(String)}
777         */
778        @Deprecated
779        public static String shaHex(String data) {
780            return sha1Hex(data);
781        }
782    
783        /**
784         * Updates the given {@link MessageDigest}.
785         *
786         * @param messageDigest
787         *            the {@link MessageDigest} to update
788         * @param valueToDigest
789         *            the value to update the {@link MessageDigest} with
790         * @return the updated {@link MessageDigest}
791         * @since 1.7
792         */
793        public static MessageDigest updateDigest(final MessageDigest messageDigest, byte[] valueToDigest) {
794            messageDigest.update(valueToDigest);
795            return messageDigest;
796        }
797    
798        /**
799         * Updates the given {@link MessageDigest}.
800         *
801         * @param messageDigest
802         *            the {@link MessageDigest} to update
803         * @param valueToDigest
804         *            the value to update the {@link MessageDigest} with
805         * @return the updated {@link MessageDigest}
806         * @since 1.7
807         */
808        public static MessageDigest updateDigest(final MessageDigest messageDigest, final String valueToDigest) {
809            messageDigest.update(getBytesUtf8(valueToDigest));
810            return messageDigest;
811        }
812    }