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 }