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