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.BufferedInputStream;
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.nio.ByteBuffer;
26  import java.security.InvalidKeyException;
27  import java.security.Key;
28  import java.security.NoSuchAlgorithmException;
29  
30  import javax.crypto.Mac;
31  import javax.crypto.spec.SecretKeySpec;
32  
33  import org.apache.commons.codec.binary.Hex;
34  import org.apache.commons.codec.binary.StringUtils;
35  
36  /**
37   * Simplifies common {@link javax.crypto.Mac} tasks. This class is immutable and thread-safe.
38   * However the Mac may not be.
39   * <p>
40   * <strong>Note: Not all JCE implementations support all algorithms. If not supported, an IllegalArgumentException is
41   * thrown.</strong>
42   * <p>
43   * Sample usage:
44   * <pre>
45   * import static HmacAlgorithms.*;
46   * byte[] key = {1,2,3,4}; // don't use this actual key!
47   * String valueToDigest = "The quick brown fox jumps over the lazy dog";
48   * byte[] hmac = new HmacUtils(HMAC_SHA_224, key).hmac(valueToDigest);
49   * // Mac re-use
50   * HmacUtils hm1 = new HmacUtils("HmacAlgoName", key); // use a valid name here!
51   * String hexPom = hm1.hmacHex(new File("pom.xml"));
52   * String hexNot = hm1.hmacHex(new File("NOTICE.txt"));
53   * </pre>
54   * @since 1.10
55   * @version $Id: HmacUtils.java 1811344 2017-10-06 15:19:57Z ggregory $
56   */
57  public final class HmacUtils {
58  
59      private static final int STREAM_BUFFER_LENGTH = 1024;
60  
61      /**
62      * Returns whether this algorithm is available
63      *
64      *@param name the name to check
65      * @return whether this algorithm is available
66      * @since 1.11
67      */
68      public static boolean isAvailable(final String name) {
69          try {
70              Mac.getInstance(name);
71              return true;
72          } catch (final NoSuchAlgorithmException e) {
73              return false;
74          }
75      }
76  
77      /**
78      * Returns whether this algorithm is available
79      *
80      *@param name the name to check
81      * @return whether this algorithm is available
82      * @since 1.11
83      */
84      public static boolean isAvailable(final HmacAlgorithms name) {
85          try {
86              Mac.getInstance(name.getName());
87              return true;
88          } catch (final NoSuchAlgorithmException e) {
89              return false;
90          }
91      }
92  
93      /**
94       * Returns an initialized <code>Mac</code> for the HmacMD5 algorithm.
95       * <p>
96       * Every implementation of the Java platform is required to support this standard Mac algorithm.
97       * </p>
98       *
99       * @param key
100      *            They key for the keyed digest (must not be null)
101      * @return A Mac instance initialized with the given key.
102      * @see Mac#getInstance(String)
103      * @see Mac#init(Key)
104      * @throws IllegalArgumentException
105      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
106      * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_MD5, byte[])}
107      */
108     @Deprecated
109     public static Mac getHmacMd5(final byte[] key) {
110         return getInitializedMac(HmacAlgorithms.HMAC_MD5, key);
111     }
112 
113     /**
114      * Returns an initialized <code>Mac</code> for the HmacSHA1 algorithm.
115      * <p>
116      * Every implementation of the Java platform is required to support this standard Mac algorithm.
117      * </p>
118      *
119      * @param key
120      *            They key for the keyed digest (must not be null)
121      * @return A Mac instance initialized with the given key.
122      * @see Mac#getInstance(String)
123      * @see Mac#init(Key)
124      * @throws IllegalArgumentException
125      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
126      * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_1, byte[])}
127      */
128     @Deprecated
129     public static Mac getHmacSha1(final byte[] key) {
130         return getInitializedMac(HmacAlgorithms.HMAC_SHA_1, key);
131     }
132 
133     /**
134      * Returns an initialized <code>Mac</code> for the HmacSHA256 algorithm.
135      * <p>
136      * Every implementation of the Java platform is required to support this standard Mac algorithm.
137      * </p>
138      *
139      * @param key
140      *            They key for the keyed digest (must not be null)
141      * @return A Mac instance initialized with the given key.
142      * @see Mac#getInstance(String)
143      * @see Mac#init(Key)
144      * @throws IllegalArgumentException
145      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
146      * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_256, byte[])}
147      */
148     @Deprecated
149     public static Mac getHmacSha256(final byte[] key) {
150         return getInitializedMac(HmacAlgorithms.HMAC_SHA_256, key);
151     }
152 
153     /**
154      * Returns an initialized <code>Mac</code> for the HmacSHA384 algorithm.
155      * <p>
156      * Every implementation of the Java platform is <em>not</em> required to support this Mac algorithm.
157      * </p>
158      *
159      * @param key
160      *            They key for the keyed digest (must not be null)
161      * @return A Mac instance initialized with the given key.
162      * @see Mac#getInstance(String)
163      * @see Mac#init(Key)
164      * @throws IllegalArgumentException
165      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
166      * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_384, byte[])}
167      */
168     @Deprecated
169     public static Mac getHmacSha384(final byte[] key) {
170         return getInitializedMac(HmacAlgorithms.HMAC_SHA_384, key);
171     }
172 
173     /**
174      * Returns an initialized <code>Mac</code> for the HmacSHA512 algorithm.
175      * <p>
176      * Every implementation of the Java platform is <em>not</em> required to support this Mac algorithm.
177      * </p>
178      *
179      * @param key
180      *            They key for the keyed digest (must not be null)
181      * @return A Mac instance initialized with the given key.
182      * @see Mac#getInstance(String)
183      * @see Mac#init(Key)
184      * @throws IllegalArgumentException
185      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
186      * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_512, byte[])}
187      */
188     @Deprecated
189     public static Mac getHmacSha512(final byte[] key) {
190         return getInitializedMac(HmacAlgorithms.HMAC_SHA_512, key);
191     }
192 
193     /**
194      * Returns an initialized <code>Mac</code> for the given <code>algorithm</code>.
195      *
196      * @param algorithm
197      *            the name of the algorithm requested. See
198      *            <a href= "http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"
199      *            >Appendix A in the Java Cryptography Architecture Reference Guide</a> for information about standard
200      *            algorithm names.
201      * @param key
202      *            They key for the keyed digest (must not be null)
203      * @return A Mac instance initialized with the given key.
204      * @see Mac#getInstance(String)
205      * @see Mac#init(Key)
206      * @throws IllegalArgumentException
207      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
208      */
209     public static Mac getInitializedMac(final HmacAlgorithms algorithm, final byte[] key) {
210         return getInitializedMac(algorithm.getName(), key);
211     }
212 
213     /**
214      * Returns an initialized <code>Mac</code> for the given <code>algorithm</code>.
215      *
216      * @param algorithm
217      *            the name of the algorithm requested. See
218      *            <a href= "http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"
219      *            >Appendix A in the Java Cryptography Architecture Reference Guide</a> for information about standard
220      *            algorithm names.
221      * @param key
222      *            They key for the keyed digest (must not be null)
223      * @return A Mac instance initialized with the given key.
224      * @see Mac#getInstance(String)
225      * @see Mac#init(Key)
226      * @throws IllegalArgumentException
227      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
228      */
229     public static Mac getInitializedMac(final String algorithm, final byte[] key) {
230 
231         if (key == null) {
232             throw new IllegalArgumentException("Null key");
233         }
234 
235         try {
236             final SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
237             final Mac mac = Mac.getInstance(algorithm);
238             mac.init(keySpec);
239             return mac;
240         } catch (final NoSuchAlgorithmException e) {
241             throw new IllegalArgumentException(e);
242         } catch (final InvalidKeyException e) {
243             throw new IllegalArgumentException(e);
244         }
245     }
246 
247     // hmacMd5
248 
249     /**
250      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
251      *
252      * @param key
253      *            They key for the keyed digest (must not be null)
254      * @param valueToDigest
255      *            The value (data) which should to digest (maybe empty or null)
256      * @return HmacMD5 MAC for the given key and value
257      * @throws IllegalArgumentException
258      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
259      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmac(byte[])}
260      */
261     @Deprecated
262     public static byte[] hmacMd5(final byte[] key, final byte[] valueToDigest) {
263         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
264     }
265 
266     /**
267      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
268      *
269      * @param key
270      *            They key for the keyed digest (must not be null)
271      * @param valueToDigest
272      *            The value (data) which should to digest
273      *            <p>
274      *            The InputStream must not be null and will not be closed
275      *            </p>
276      * @return HmacMD5 MAC for the given key and value
277      * @throws IOException
278      *             If an I/O error occurs.
279      * @throws IllegalArgumentException
280      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
281      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmac(InputStream)}
282      */
283     @Deprecated
284     public static byte[] hmacMd5(final byte[] key, final InputStream valueToDigest) throws IOException {
285         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
286     }
287 
288     /**
289      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
290      *
291      * @param key
292      *            They key for the keyed digest (must not be null)
293      * @param valueToDigest
294      *            The value (data) which should to digest (maybe empty or null)
295      * @return HmacMD5 MAC for the given key and value
296      * @throws IllegalArgumentException
297      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
298      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, String).hmac(String)}
299      */
300     @Deprecated
301     public static byte[] hmacMd5(final String key, final String valueToDigest) {
302         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
303     }
304 
305     /**
306      * Returns a HmacMD5 Message Authentication Code (MAC) as a hex string (lowercase) for the given key and value.
307      *
308      * @param key
309      *            They key for the keyed digest (must not be null)
310      * @param valueToDigest
311      *            The value (data) which should to digest (maybe empty or null)
312      * @return HmacMD5 MAC for the given key and value as a hex string (lowercase)
313      * @throws IllegalArgumentException
314      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
315      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(byte[])}
316      */
317     @Deprecated
318     public static String hmacMd5Hex(final byte[] key, final byte[] valueToDigest) {
319         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
320     }
321 
322     /**
323      * Returns a HmacMD5 Message Authentication Code (MAC) as a hex string (lowercase) for the given key and value.
324      *
325      * @param key
326      *            They key for the keyed digest (must not be null)
327      * @param valueToDigest
328      *            The value (data) which should to digest
329      *            <p>
330      *            The InputStream must not be null and will not be closed
331      *            </p>
332      * @return HmacMD5 MAC for the given key and value as a hex string (lowercase)
333      * @throws IOException
334      *             If an I/O error occurs.
335      * @throws IllegalArgumentException
336      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
337      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(InputStream)}
338      */
339     @Deprecated
340     public static String hmacMd5Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
341         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
342     }
343 
344     /**
345      * Returns a HmacMD5 Message Authentication Code (MAC) as a hex string (lowercase) for the given key and value.
346      *
347      * @param key
348      *            They key for the keyed digest (must not be null)
349      * @param valueToDigest
350      *            The value (data) which should to digest (maybe empty or null)
351      * @return HmacMD5 MAC for the given key and value as a hex string (lowercase)
352      * @throws IllegalArgumentException
353      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
354      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, String).hmacHex(String)}
355      */
356     @Deprecated
357     public static String hmacMd5Hex(final String key, final String valueToDigest) {
358         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
359     }
360 
361     // hmacSha1
362 
363     /**
364      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
365      *
366      * @param key
367      *            They key for the keyed digest (must not be null)
368      * @param valueToDigest
369      *            The value (data) which should to digest (maybe empty or null)
370      * @return HmacSHA1 MAC for the given key and value
371      * @throws IllegalArgumentException
372      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
373      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmac(byte[])}
374      */
375     @Deprecated
376     public static byte[] hmacSha1(final byte[] key, final byte[] valueToDigest) {
377         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
378     }
379 
380     /**
381      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
382      *
383      * @param key
384      *            They key for the keyed digest (must not be null)
385      * @param valueToDigest
386      *            The value (data) which should to digest
387      *            <p>
388      *            The InputStream must not be null and will not be closed
389      *            </p>
390      * @return HmacSHA1 MAC for the given key and value
391      * @throws IOException
392      *             If an I/O error occurs.
393      * @throws IllegalArgumentException
394      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
395      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmac(InputStream)}
396      */
397     @Deprecated
398     public static byte[] hmacSha1(final byte[] key, final InputStream valueToDigest) throws IOException {
399         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
400     }
401 
402     /**
403      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
404      *
405      * @param key
406      *            They key for the keyed digest (must not be null)
407      * @param valueToDigest
408      *            The value (data) which should to digest (maybe empty or null)
409      * @return HmacSHA1 MAC for the given key and value
410      * @throws IllegalArgumentException
411      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
412      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmac(String)}
413      */
414     @Deprecated
415     public static byte[] hmacSha1(final String key, final String valueToDigest) {
416         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
417     }
418 
419     /**
420      * Returns a HmacSHA1 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
421      *
422      * @param key
423      *            They key for the keyed digest (must not be null)
424      * @param valueToDigest
425      *            The value (data) which should to digest (maybe empty or null)
426      * @return HmacSHA1 MAC for the given key and value as hex string (lowercase)
427      * @throws IllegalArgumentException
428      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
429      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(byte[])}
430      */
431     @Deprecated
432     public static String hmacSha1Hex(final byte[] key, final byte[] valueToDigest) {
433         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
434     }
435 
436     /**
437      * Returns a HmacSHA1 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
438      *
439      * @param key
440      *            They key for the keyed digest (must not be null)
441      * @param valueToDigest
442      *            The value (data) which should to digest
443      *            <p>
444      *            The InputStream must not be null and will not be closed
445      *            </p>
446      * @return HmacSHA1 MAC for the given key and value as hex string (lowercase)
447      * @throws IOException
448      *             If an I/O error occurs.
449      * @throws IllegalArgumentException
450      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
451      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(InputStream)}
452      */
453     @Deprecated
454     public static String hmacSha1Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
455         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
456     }
457 
458     /**
459      * Returns a HmacSHA1 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
460      *
461      * @param key
462      *            They key for the keyed digest (must not be null)
463      * @param valueToDigest
464      *            The value (data) which should to digest (maybe empty or null)
465      * @return HmacSHA1 MAC for the given key and value as hex string (lowercase)
466      * @throws IllegalArgumentException
467      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
468      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmacHex(String)}
469      */
470     @Deprecated
471     public static String hmacSha1Hex(final String key, final String valueToDigest) {
472         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
473     }
474 
475     // hmacSha256
476 
477     /**
478      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
479      *
480      * @param key
481      *            They key for the keyed digest (must not be null)
482      * @param valueToDigest
483      *            The value (data) which should to digest (maybe empty or null)
484      * @return HmacSHA256 MAC for the given key and value
485      * @throws IllegalArgumentException
486      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
487      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(byte[])}
488      */
489     @Deprecated
490     public static byte[] hmacSha256(final byte[] key, final byte[] valueToDigest) {
491         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
492     }
493 
494     /**
495      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
496      *
497      * @param key
498      *            They key for the keyed digest (must not be null)
499      * @param valueToDigest
500      *            The value (data) which should to digest
501      *            <p>
502      *            The InputStream must not be null and will not be closed
503      *            </p>
504      * @return HmacSHA256 MAC for the given key and value
505      * @throws IOException
506      *             If an I/O error occurs.
507      * @throws IllegalArgumentException
508      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
509      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(InputStream)}
510      */
511     @Deprecated
512     public static byte[] hmacSha256(final byte[] key, final InputStream valueToDigest) throws IOException {
513         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
514     }
515 
516     /**
517      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
518      *
519      * @param key
520      *            They key for the keyed digest (must not be null)
521      * @param valueToDigest
522      *            The value (data) which should to digest (maybe empty or null)
523      * @return HmacSHA256 MAC for the given key and value
524      * @throws IllegalArgumentException
525      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
526      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmac(String)}
527      */
528     @Deprecated
529     public static byte[] hmacSha256(final String key, final String valueToDigest) {
530         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
531     }
532 
533     /**
534      * Returns a HmacSHA256 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
535      *
536      * @param key
537      *            They key for the keyed digest (must not be null)
538      * @param valueToDigest
539      *            The value (data) which should to digest (maybe empty or null)
540      * @return HmacSHA256 MAC for the given key and value as hex string (lowercase)
541      * @throws IllegalArgumentException
542      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
543      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(byte[])}
544      */
545     @Deprecated
546     public static String hmacSha256Hex(final byte[] key, final byte[] valueToDigest) {
547         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
548     }
549 
550     /**
551      * Returns a HmacSHA256 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
552      *
553      * @param key
554      *            They key for the keyed digest (must not be null)
555      * @param valueToDigest
556      *            The value (data) which should to digest
557      *            <p>
558      *            The InputStream must not be null and will not be closed
559      *            </p>
560      * @return HmacSHA256 MAC for the given key and value as hex string (lowercase)
561      * @throws IOException
562      *             If an I/O error occurs.
563      * @throws IllegalArgumentException
564      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
565      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(InputStream)}
566      */
567     @Deprecated
568     public static String hmacSha256Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
569         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
570     }
571 
572     /**
573      * Returns a HmacSHA256 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
574      *
575      * @param key
576      *            They key for the keyed digest (must not be null)
577      * @param valueToDigest
578      *            The value (data) which should to digest (maybe empty or null)
579      * @return HmacSHA256 MAC for the given key and value as hex string (lowercase)
580      * @throws IllegalArgumentException
581      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
582      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmacHex(String)}
583      */
584     @Deprecated
585     public static String hmacSha256Hex(final String key, final String valueToDigest) {
586         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
587     }
588 
589     // hmacSha384
590 
591     /**
592      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
593      *
594      * @param key
595      *            They key for the keyed digest (must not be null)
596      * @param valueToDigest
597      *            The value (data) which should to digest (maybe empty or null)
598      * @return HmacSHA384 MAC for the given key and value
599      * @throws IllegalArgumentException
600      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
601      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(byte[])}
602      */
603     @Deprecated
604     public static byte[] hmacSha384(final byte[] key, final byte[] valueToDigest) {
605         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
606     }
607 
608     /**
609      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
610      *
611      * @param key
612      *            They key for the keyed digest (must not be null)
613      * @param valueToDigest
614      *            The value (data) which should to digest
615      *            <p>
616      *            The InputStream must not be null and will not be closed
617      *            </p>
618      * @return HmacSHA384 MAC for the given key and value
619      * @throws IOException
620      *             If an I/O error occurs.
621      * @throws IllegalArgumentException
622      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
623      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(InputStream)}
624      */
625     @Deprecated
626     public static byte[] hmacSha384(final byte[] key, final InputStream valueToDigest) throws IOException {
627         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
628     }
629 
630     /**
631      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
632      *
633      * @param key
634      *            They key for the keyed digest (must not be null)
635      * @param valueToDigest
636      *            The value (data) which should to digest (maybe empty or null)
637      * @return HmacSHA384 MAC for the given key and value
638      * @throws IllegalArgumentException
639      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
640      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmac(String)}
641      */
642     @Deprecated
643     public static byte[] hmacSha384(final String key, final String valueToDigest) {
644         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
645     }
646 
647     /**
648      * Returns a HmacSHA384 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
649      *
650      * @param key
651      *            They key for the keyed digest (must not be null)
652      * @param valueToDigest
653      *            The value (data) which should to digest (maybe empty or null)
654      * @return HmacSHA384 MAC for the given key and value as hex string (lowercase)
655      * @throws IllegalArgumentException
656      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
657      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(byte[])}
658      */
659     @Deprecated
660     public static String hmacSha384Hex(final byte[] key, final byte[] valueToDigest) {
661         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
662     }
663 
664     /**
665      * Returns a HmacSHA384 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
666      *
667      * @param key
668      *            They key for the keyed digest (must not be null)
669      * @param valueToDigest
670      *            The value (data) which should to digest
671      *            <p>
672      *            The InputStream must not be null and will not be closed
673      *            </p>
674      * @return HmacSHA384 MAC for the given key and value as hex string (lowercase)
675      * @throws IOException
676      *             If an I/O error occurs.
677      * @throws IllegalArgumentException
678      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
679      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(InputStream)}
680      */
681     @Deprecated
682     public static String hmacSha384Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
683         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
684     }
685 
686     /**
687      * Returns a HmacSHA384 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
688      *
689      * @param key
690      *            They key for the keyed digest (must not be null)
691      * @param valueToDigest
692      *            The value (data) which should to digest (maybe empty or null)
693      * @return HmacSHA384 MAC for the given key and value as hex string (lowercase)
694      * @throws IllegalArgumentException
695      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
696      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmacHex(String)}
697      */
698     @Deprecated
699     public static String hmacSha384Hex(final String key, final String valueToDigest) {
700         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
701     }
702 
703     // hmacSha512
704 
705     /**
706      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
707      *
708      * @param key
709      *            They key for the keyed digest (must not be null)
710      * @param valueToDigest
711      *            The value (data) which should to digest (maybe empty or null)
712      * @return HmacSHA512 MAC for the given key and value
713      * @throws IllegalArgumentException
714      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
715      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(byte[])}
716      */
717     @Deprecated
718     public static byte[] hmacSha512(final byte[] key, final byte[] valueToDigest) {
719         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
720     }
721 
722     /**
723      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
724      *
725      * @param key
726      *            They key for the keyed digest (must not be null)
727      * @param valueToDigest
728      *            The value (data) which should to digest
729      *            <p>
730      *            The InputStream must not be null and will not be closed
731      *            </p>
732      * @return HmacSHA512 MAC for the given key and value
733      * @throws IOException
734      *             If an I/O error occurs.
735      * @throws IllegalArgumentException
736      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
737      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(InputStream)}
738      */
739     @Deprecated
740     public static byte[] hmacSha512(final byte[] key, final InputStream valueToDigest) throws IOException {
741         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
742     }
743 
744     /**
745      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
746      *
747      * @param key
748      *            They key for the keyed digest (must not be null)
749      * @param valueToDigest
750      *            The value (data) which should to digest (maybe empty or null)
751      * @return HmacSHA512 MAC for the given key and value
752      * @throws IllegalArgumentException
753      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
754      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmac(String)}
755      */
756     @Deprecated
757     public static byte[] hmacSha512(final String key, final String valueToDigest) {
758         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
759     }
760 
761     /**
762      * Returns a HmacSHA512 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
763      *
764      * @param key
765      *            They key for the keyed digest (must not be null)
766      * @param valueToDigest
767      *            The value (data) which should to digest (maybe empty or null)
768      * @return HmacSHA512 MAC for the given key and value as hex string (lowercase)
769      * @throws IllegalArgumentException
770      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
771      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(byte[])}
772      */
773     @Deprecated
774     public static String hmacSha512Hex(final byte[] key, final byte[] valueToDigest) {
775         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
776     }
777 
778     /**
779      * Returns a HmacSHA512 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
780      *
781      * @param key
782      *            They key for the keyed digest (must not be null)
783      * @param valueToDigest
784      *            The value (data) which should to digest
785      *            <p>
786      *            The InputStream must not be null and will not be closed
787      *            </p>
788      * @return HmacSHA512 MAC for the given key and value as hex string (lowercase)
789      * @throws IOException
790      *             If an I/O error occurs.
791      * @throws IllegalArgumentException
792      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
793      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(InputStream)}
794      */
795     @Deprecated
796     public static String hmacSha512Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
797         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
798     }
799 
800     /**
801      * Returns a HmacSHA512 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
802      *
803      * @param key
804      *            They key for the keyed digest (must not be null)
805      * @param valueToDigest
806      *            The value (data) which should to digest (maybe empty or null)
807      * @return HmacSHA512 MAC for the given key and value as hex string (lowercase)
808      * @throws IllegalArgumentException
809      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
810      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmacHex(String)}
811      */
812     @Deprecated
813     public static String hmacSha512Hex(final String key, final String valueToDigest) {
814         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
815     }
816 
817     // update
818 
819     /**
820      * Resets and then updates the given {@link Mac} with the value.
821      *
822      * @param mac
823      *            the initialized {@link Mac} to update
824      * @param valueToDigest
825      *            the value to update the {@link Mac} with (maybe null or empty)
826      * @return the updated {@link Mac}
827      * @throws IllegalStateException
828      *             if the Mac was not initialized
829      */
830     public static Mac updateHmac(final Mac mac, final byte[] valueToDigest) {
831         mac.reset();
832         mac.update(valueToDigest);
833         return mac;
834     }
835 
836     /**
837      * Resets and then updates the given {@link Mac} with the value.
838      *
839      * @param mac
840      *            the initialized {@link Mac} to update
841      * @param valueToDigest
842      *            the value to update the {@link Mac} with
843      *            <p>
844      *            The InputStream must not be null and will not be closed
845      *            </p>
846      * @return the updated {@link Mac}
847      * @throws IOException
848      *             If an I/O error occurs.
849      * @throws IllegalStateException
850      *             If the Mac was not initialized
851      */
852     public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException {
853         mac.reset();
854         final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
855         int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
856 
857         while (read > -1) {
858             mac.update(buffer, 0, read);
859             read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
860         }
861 
862         return mac;
863     }
864 
865     /**
866      * Resets and then updates the given {@link Mac} with the value.
867      *
868      * @param mac
869      *            the initialized {@link Mac} to update
870      * @param valueToDigest
871      *            the value to update the {@link Mac} with (maybe null or empty)
872      * @return the updated {@link Mac}
873      * @throws IllegalStateException
874      *             if the Mac was not initialized
875      */
876     public static Mac updateHmac(final Mac mac, final String valueToDigest) {
877         mac.reset();
878         mac.update(StringUtils.getBytesUtf8(valueToDigest));
879         return mac;
880     }
881 
882     /**
883      * Preserves binary compatibity only.
884      * As for previous versions does not provide useful behaviour
885      * @deprecated since 1.11; only useful to preserve binary compatibility
886      */
887     @Deprecated
888     public HmacUtils() {
889         this(null);
890     }
891 
892     private final Mac mac;
893 
894     private HmacUtils(final Mac mac) {
895         this.mac = mac;
896     }
897 
898     /**
899      * Creates an instance using the provided algorithm type.
900      *
901      * @param algorithm to use
902      * @param  key the key to use
903      * @throws IllegalArgumentException
904      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
905      * @since 1.11
906      */
907     public HmacUtils(final String algorithm, final byte[] key) {
908         this(getInitializedMac(algorithm, key));
909     }
910 
911     /**
912      * Creates an instance using the provided algorithm type.
913      *
914      * @param algorithm to use
915      * @param  key the key to use
916      * @throws IllegalArgumentException
917      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
918      * @since 1.11
919      */
920     public HmacUtils(final String algorithm, final String key) {
921         this(algorithm, StringUtils.getBytesUtf8(key));
922     }
923 
924     /**
925      * Creates an instance using the provided algorithm type.
926      *
927      * @param algorithm to use
928      * @param  key the key to use
929      * @throws IllegalArgumentException
930      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
931      * @since 1.11
932      */
933     public HmacUtils(final HmacAlgorithms algorithm, final String key) {
934         this(algorithm.getName(), StringUtils.getBytesUtf8(key));
935     }
936 
937     /**
938      * Creates an instance using the provided algorithm type.
939      *
940      * @param algorithm to use.
941      * @param key the key to use
942      * @throws IllegalArgumentException
943      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
944      * @since 1.11
945      */
946     public HmacUtils(final HmacAlgorithms algorithm, final byte[] key) {
947         this(algorithm.getName(), key);
948     }
949 
950     /**
951      * Returns the digest for the input data.
952      *
953      * @param valueToDigest the input to use
954      * @return the digest as a byte[]
955      * @since 1.11
956      */
957     public byte[] hmac(final byte[] valueToDigest) {
958         return mac.doFinal(valueToDigest);
959     }
960 
961     /**
962      * Returns the digest for the input data.
963      *
964      * @param valueToDigest the input to use
965      * @return the digest as a hex String
966      * @since 1.11
967      */
968     public String hmacHex(final byte[] valueToDigest) {
969         return Hex.encodeHexString(hmac(valueToDigest));
970     }
971 
972     /**
973      * Returns the digest for the input data.
974      *
975      * @param valueToDigest the input to use, treated as UTF-8
976      * @return the digest as a byte[]
977      * @since 1.11
978      */
979     public byte[] hmac(final String valueToDigest) {
980         return mac.doFinal(StringUtils.getBytesUtf8(valueToDigest));
981     }
982 
983     /**
984      * Returns the digest for the input data.
985      *
986      * @param valueToDigest the input to use, treated as UTF-8
987      * @return the digest as a hex String
988      * @since 1.11
989      */
990     public String hmacHex(final String valueToDigest) {
991         return Hex.encodeHexString(hmac(valueToDigest));
992     }
993 
994     /**
995      * Returns the digest for the input data.
996      *
997      * @param valueToDigest the input to use
998      * @return the digest as a byte[]
999      * @since 1.11
1000      */
1001     public byte[] hmac(final ByteBuffer valueToDigest) {
1002         mac.update(valueToDigest);
1003         return mac.doFinal();
1004     }
1005 
1006     /**
1007      * Returns the digest for the input data.
1008      *
1009      * @param valueToDigest the input to use
1010      * @return the digest as a hex String
1011      * @since 1.11
1012      */
1013     public String hmacHex(final ByteBuffer valueToDigest) {
1014         return Hex.encodeHexString(hmac(valueToDigest));
1015     }
1016 
1017     /**
1018      * Returns the digest for the stream.
1019      *
1020      * @param valueToDigest
1021      *            the data to use
1022      *            <p>
1023      *            The InputStream must not be null and will not be closed
1024      *            </p>
1025      * @return the digest
1026      * @throws IOException
1027      *             If an I/O error occurs.
1028      * @since 1.11
1029      */
1030     public byte[] hmac(final InputStream valueToDigest) throws IOException {
1031         final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
1032         int read;
1033 
1034         while ((read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH) ) > -1) {
1035             mac.update(buffer, 0, read);
1036         }
1037         return mac.doFinal();
1038     }
1039 
1040     /**
1041      * Returns the digest for the stream.
1042      *
1043      * @param valueToDigest
1044      *            the data to use
1045      *            <p>
1046      *            The InputStream must not be null and will not be closed
1047      *            </p>
1048      * @return the digest as a hex String
1049      * @throws IOException
1050      *             If an I/O error occurs.
1051      * @since 1.11
1052      */
1053     public String hmacHex(final InputStream valueToDigest) throws IOException {
1054         return Hex.encodeHexString(hmac(valueToDigest));
1055     }
1056 
1057     /**
1058      * Returns the digest for the file.
1059      *
1060      * @param valueToDigest the file to use
1061      * @return the digest
1062      * @throws IOException
1063      *             If an I/O error occurs.
1064      * @since 1.11
1065      */
1066     public byte[] hmac(final File valueToDigest) throws IOException {
1067         final BufferedInputStream stream = new BufferedInputStream(new FileInputStream(valueToDigest));
1068         try {
1069             return hmac(stream);
1070         } finally {
1071             stream.close();
1072         }
1073     }
1074 
1075     /**
1076      * Returns the digest for the file.
1077      *
1078      * @param valueToDigest the file to use
1079      * @return the digest as a hex String
1080      * @throws IOException
1081      *             If an I/O error occurs.
1082      * @since 1.11
1083      */
1084     public String hmacHex(final File valueToDigest) throws IOException {
1085         return Hex.encodeHexString(hmac(valueToDigest));
1086     }
1087 
1088 }