View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.codec.digest;
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.security.MessageDigest;
23  import java.security.NoSuchAlgorithmException;
24  
25  import org.apache.commons.codec.binary.Hex;
26  import org.apache.commons.codec.binary.StringUtils;
27  
28  /**
29   * Operations to simplify common {@link java.security.MessageDigest} tasks. This class is thread safe.
30   * 
31   * @author Apache Software Foundation
32   * @version $Id: DigestUtils.java 1157192 2011-08-12 17:27:38Z ggregory $
33   */
34  public class DigestUtils {
35  
36      private static final int STREAM_BUFFER_LENGTH = 1024;
37  
38      /**
39       * Read through an InputStream and returns the digest for the data
40       * 
41       * @param digest
42       *            The MessageDigest to use (e.g. MD5)
43       * @param data
44       *            Data to digest
45       * @return MD5 digest
46       * @throws IOException
47       *             On error reading from the stream
48       */
49      private static byte[] digest(MessageDigest digest, InputStream data) throws IOException {
50          byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
51          int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
52  
53          while (read > -1) {
54              digest.update(buffer, 0, read);
55              read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
56          }
57  
58          return digest.digest();
59      }
60  
61      /**
62       * Calls {@link StringUtils#getBytesUtf8(String)}
63       * 
64       * @param data
65       *            the String to encode
66       * @return encoded bytes
67       */
68      private static byte[] getBytesUtf8(String data) {
69          return StringUtils.getBytesUtf8(data);
70      }
71  
72      /**
73       * Returns a <code>MessageDigest</code> for the given <code>algorithm</code>.
74       * 
75       * @param algorithm
76       *            the name of the algorithm requested. See <a
77       *            href="http://java.sun.com/j2se/1.3/docs/guide/security/CryptoSpec.html#AppA">Appendix A in the Java
78       *            Cryptography Architecture API Specification & Reference</a> for information about standard algorithm
79       *            names.
80       * @return An MD5 digest instance.
81       * @see MessageDigest#getInstance(String)
82       * @throws RuntimeException
83       *             when a {@link java.security.NoSuchAlgorithmException} is caught.
84       */
85      static MessageDigest getDigest(String algorithm) {
86          try {
87              return MessageDigest.getInstance(algorithm);
88          } catch (NoSuchAlgorithmException e) {
89              throw new RuntimeException(e.getMessage());
90          }
91      }
92  
93      /**
94       * Returns an MD5 MessageDigest.
95       * 
96       * @return An MD5 digest instance.
97       * @throws RuntimeException
98       *             when a {@link java.security.NoSuchAlgorithmException} is caught.
99       */
100     private static MessageDigest getMd5Digest() {
101         return getDigest("MD5");
102     }
103 
104     /**
105      * Returns an SHA-256 digest.
106      * <p>
107      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
108      * </p>
109      * 
110      * @return An SHA-256 digest instance.
111      * @throws RuntimeException
112      *             when a {@link java.security.NoSuchAlgorithmException} is caught.
113      */
114     private static MessageDigest getSha256Digest() {
115         return getDigest("SHA-256");
116     }
117 
118     /**
119      * Returns an SHA-384 digest.
120      * <p>
121      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
122      * </p>
123      * 
124      * @return An SHA-384 digest instance.
125      * @throws RuntimeException
126      *             when a {@link java.security.NoSuchAlgorithmException} is caught.
127      */
128     private static MessageDigest getSha384Digest() {
129         return getDigest("SHA-384");
130     }
131 
132     /**
133      * Returns an SHA-512 digest.
134      * <p>
135      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
136      * </p>
137      * 
138      * @return An SHA-512 digest instance.
139      * @throws RuntimeException
140      *             when a {@link java.security.NoSuchAlgorithmException} is caught.
141      */
142     private static MessageDigest getSha512Digest() {
143         return getDigest("SHA-512");
144     }
145 
146     /**
147      * Returns an SHA-1 digest.
148      * 
149      * @return An SHA-1 digest instance.
150      * @throws RuntimeException
151      *             when a {@link java.security.NoSuchAlgorithmException} is caught.
152      */
153     private static MessageDigest getShaDigest() {
154         return getDigest("SHA");
155     }
156 
157     /**
158      * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
159      * 
160      * @param data
161      *            Data to digest
162      * @return MD5 digest
163      */
164     public static byte[] md5(byte[] data) {
165         return getMd5Digest().digest(data);
166     }
167 
168     /**
169      * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
170      * 
171      * @param data
172      *            Data to digest
173      * @return MD5 digest
174      * @throws IOException
175      *             On error reading from the stream
176      * @since 1.4
177      */
178     public static byte[] md5(InputStream data) throws IOException {
179         return digest(getMd5Digest(), data);
180     }
181 
182     /**
183      * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
184      * 
185      * @param data
186      *            Data to digest
187      * @return MD5 digest
188      */
189     public static byte[] md5(String data) {
190         return md5(getBytesUtf8(data));
191     }
192 
193     /**
194      * Calculates the MD5 digest and returns the value as a 32 character hex string.
195      * 
196      * @param data
197      *            Data to digest
198      * @return MD5 digest as a hex string
199      */
200     public static String md5Hex(byte[] data) {
201         return Hex.encodeHexString(md5(data));
202     }
203 
204     /**
205      * Calculates the MD5 digest and returns the value as a 32 character hex string.
206      * 
207      * @param data
208      *            Data to digest
209      * @return MD5 digest as a hex string
210      * @throws IOException
211      *             On error reading from the stream
212      * @since 1.4
213      */
214     public static String md5Hex(InputStream data) throws IOException {
215         return Hex.encodeHexString(md5(data));
216     }
217 
218     /**
219      * Calculates the MD5 digest and returns the value as a 32 character hex string.
220      * 
221      * @param data
222      *            Data to digest
223      * @return MD5 digest as a hex string
224      */
225     public static String md5Hex(String data) {
226         return Hex.encodeHexString(md5(data));
227     }
228 
229     /**
230      * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
231      * 
232      * @param data
233      *            Data to digest
234      * @return SHA-1 digest
235      */
236     public static byte[] sha(byte[] data) {
237         return getShaDigest().digest(data);
238     }
239 
240     /**
241      * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
242      * 
243      * @param data
244      *            Data to digest
245      * @return SHA-1 digest
246      * @throws IOException
247      *             On error reading from the stream
248      * @since 1.4
249      */
250     public static byte[] sha(InputStream data) throws IOException {
251         return digest(getShaDigest(), data);
252     }
253 
254     /**
255      * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
256      * 
257      * @param data
258      *            Data to digest
259      * @return SHA-1 digest
260      */
261     public static byte[] sha(String data) {
262         return sha(getBytesUtf8(data));
263     }
264 
265     /**
266      * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
267      * <p>
268      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
269      * </p>
270      * 
271      * @param data
272      *            Data to digest
273      * @return SHA-256 digest
274      * @since 1.4
275      */
276     public static byte[] sha256(byte[] data) {
277         return getSha256Digest().digest(data);
278     }
279 
280     /**
281      * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
282      * <p>
283      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
284      * </p>
285      * 
286      * @param data
287      *            Data to digest
288      * @return SHA-256 digest
289      * @throws IOException
290      *             On error reading from the stream
291      * @since 1.4
292      */
293     public static byte[] sha256(InputStream data) throws IOException {
294         return digest(getSha256Digest(), data);
295     }
296 
297     /**
298      * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
299      * <p>
300      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
301      * </p>
302      * 
303      * @param data
304      *            Data to digest
305      * @return SHA-256 digest
306      * @since 1.4
307      */
308     public static byte[] sha256(String data) {
309         return sha256(getBytesUtf8(data));
310     }
311 
312     /**
313      * Calculates the SHA-256 digest and returns the value as a hex string.
314      * <p>
315      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
316      * </p>
317      * 
318      * @param data
319      *            Data to digest
320      * @return SHA-256 digest as a hex string
321      * @since 1.4
322      */
323     public static String sha256Hex(byte[] data) {
324         return Hex.encodeHexString(sha256(data));
325     }
326 
327     /**
328      * Calculates the SHA-256 digest and returns the value as a hex string.
329      * <p>
330      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
331      * </p>
332      * 
333      * @param data
334      *            Data to digest
335      * @return SHA-256 digest as a hex string
336      * @throws IOException
337      *             On error reading from the stream
338      * @since 1.4
339      */
340     public static String sha256Hex(InputStream data) throws IOException {
341         return Hex.encodeHexString(sha256(data));
342     }
343 
344     /**
345      * Calculates the SHA-256 digest and returns the value as a hex string.
346      * <p>
347      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
348      * </p>
349      * 
350      * @param data
351      *            Data to digest
352      * @return SHA-256 digest as a hex string
353      * @since 1.4
354      */
355     public static String sha256Hex(String data) {
356         return Hex.encodeHexString(sha256(data));
357     }
358 
359     /**
360      * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
361      * <p>
362      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
363      * </p>
364      * 
365      * @param data
366      *            Data to digest
367      * @return SHA-384 digest
368      * @since 1.4
369      */
370     public static byte[] sha384(byte[] data) {
371         return getSha384Digest().digest(data);
372     }
373 
374     /**
375      * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
376      * <p>
377      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
378      * </p>
379      * 
380      * @param data
381      *            Data to digest
382      * @return SHA-384 digest
383      * @throws IOException
384      *             On error reading from the stream
385      * @since 1.4
386      */
387     public static byte[] sha384(InputStream data) throws IOException {
388         return digest(getSha384Digest(), data);
389     }
390 
391     /**
392      * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
393      * <p>
394      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
395      * </p>
396      * 
397      * @param data
398      *            Data to digest
399      * @return SHA-384 digest
400      * @since 1.4
401      */
402     public static byte[] sha384(String data) {
403         return sha384(getBytesUtf8(data));
404     }
405 
406     /**
407      * Calculates the SHA-384 digest and returns the value as a hex string.
408      * <p>
409      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
410      * </p>
411      * 
412      * @param data
413      *            Data to digest
414      * @return SHA-384 digest as a hex string
415      * @since 1.4
416      */
417     public static String sha384Hex(byte[] data) {
418         return Hex.encodeHexString(sha384(data));
419     }
420 
421     /**
422      * Calculates the SHA-384 digest and returns the value as a hex string.
423      * <p>
424      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
425      * </p>
426      * 
427      * @param data
428      *            Data to digest
429      * @return SHA-384 digest as a hex string
430      * @throws IOException
431      *             On error reading from the stream
432      * @since 1.4
433      */
434     public static String sha384Hex(InputStream data) throws IOException {
435         return Hex.encodeHexString(sha384(data));
436     }
437 
438     /**
439      * Calculates the SHA-384 digest and returns the value as a hex string.
440      * <p>
441      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
442      * </p>
443      * 
444      * @param data
445      *            Data to digest
446      * @return SHA-384 digest as a hex string
447      * @since 1.4
448      */
449     public static String sha384Hex(String data) {
450         return Hex.encodeHexString(sha384(data));
451     }
452 
453     /**
454      * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
455      * <p>
456      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
457      * </p>
458      * 
459      * @param data
460      *            Data to digest
461      * @return SHA-512 digest
462      * @since 1.4
463      */
464     public static byte[] sha512(byte[] data) {
465         return getSha512Digest().digest(data);
466     }
467 
468     /**
469      * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
470      * <p>
471      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
472      * </p>
473      * 
474      * @param data
475      *            Data to digest
476      * @return SHA-512 digest
477      * @throws IOException
478      *             On error reading from the stream
479      * @since 1.4
480      */
481     public static byte[] sha512(InputStream data) throws IOException {
482         return digest(getSha512Digest(), data);
483     }
484 
485     /**
486      * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
487      * <p>
488      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
489      * </p>
490      * 
491      * @param data
492      *            Data to digest
493      * @return SHA-512 digest
494      * @since 1.4
495      */
496     public static byte[] sha512(String data) {
497         return sha512(getBytesUtf8(data));
498     }
499 
500     /**
501      * Calculates the SHA-512 digest and returns the value as a hex string.
502      * <p>
503      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
504      * </p>
505      * 
506      * @param data
507      *            Data to digest
508      * @return SHA-512 digest as a hex string
509      * @since 1.4
510      */
511     public static String sha512Hex(byte[] data) {
512         return Hex.encodeHexString(sha512(data));
513     }
514 
515     /**
516      * Calculates the SHA-512 digest and returns the value as a hex string.
517      * <p>
518      * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
519      * </p>
520      * 
521      * @param data
522      *            Data to digest
523      * @return SHA-512 digest as a hex string
524      * @throws IOException
525      *             On error reading from the stream
526      * @since 1.4
527      */
528     public static String sha512Hex(InputStream data) throws IOException {
529         return Hex.encodeHexString(sha512(data));
530     }
531 
532     /**
533      * Calculates the SHA-512 digest and returns the value as a hex string.
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-512 digest as a hex string
541      * @since 1.4
542      */
543     public static String sha512Hex(String data) {
544         return Hex.encodeHexString(sha512(data));
545     }
546 
547     /**
548      * Calculates the SHA-1 digest and returns the value as a hex string.
549      * 
550      * @param data
551      *            Data to digest
552      * @return SHA-1 digest as a hex string
553      */
554     public static String shaHex(byte[] data) {
555         return Hex.encodeHexString(sha(data));
556     }
557 
558     /**
559      * Calculates the SHA-1 digest and returns the value as a hex string.
560      * 
561      * @param data
562      *            Data to digest
563      * @return SHA-1 digest as a hex string
564      * @throws IOException
565      *             On error reading from the stream
566      * @since 1.4
567      */
568     public static String shaHex(InputStream data) throws IOException {
569         return Hex.encodeHexString(sha(data));
570     }
571 
572     /**
573      * Calculates the SHA-1 digest and returns the value as a hex string.
574      * 
575      * @param data
576      *            Data to digest
577      * @return SHA-1 digest as a hex string
578      */
579     public static String shaHex(String data) {
580         return Hex.encodeHexString(sha(data));
581     }
582 }