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 
200         if (key == null) {
201             throw new IllegalArgumentException("Null key");
202         }
203 
204         try {
205             final SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
206             final Mac mac = Mac.getInstance(algorithm);
207             mac.init(keySpec);
208             return mac;
209         } catch (final NoSuchAlgorithmException | InvalidKeyException e) {
210             throw new IllegalArgumentException(e);
211         }
212     }
213 
214     /**
215      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
216      *
217      * @param key
218      *            The key for the keyed digest (must not be null)
219      * @param valueToDigest
220      *            The value (data) which should to digest (maybe empty or null)
221      * @return HmacMD5 MAC for the given key and value
222      * @throws IllegalArgumentException
223      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
224      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmac(byte[])}
225      */
226     @Deprecated
227     public static byte[] hmacMd5(final byte[] key, final byte[] valueToDigest) {
228         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
229     }
230 
231     /**
232      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
233      *
234      * @param key
235      *            The key for the keyed digest (must not be null)
236      * @param valueToDigest
237      *            The value (data) which should to digest
238      *            <p>
239      *            The InputStream must not be null and will not be closed
240      *            </p>
241      * @return HmacMD5 MAC for the given key and value
242      * @throws IOException
243      *             If an I/O error occurs.
244      * @throws IllegalArgumentException
245      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
246      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmac(InputStream)}
247      */
248     @Deprecated
249     public static byte[] hmacMd5(final byte[] key, final InputStream valueToDigest) throws IOException {
250         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
251     }
252 
253     /**
254      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
255      *
256      * @param key
257      *            The key for the keyed digest (must not be null)
258      * @param valueToDigest
259      *            The value (data) which should to digest (maybe empty or null)
260      * @return HmacMD5 MAC for the given key and value
261      * @throws IllegalArgumentException
262      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
263      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, String).hmac(String)}
264      */
265     @Deprecated
266     public static byte[] hmacMd5(final String key, final String valueToDigest) {
267         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
268     }
269 
270     /**
271      * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
272      *
273      * @param key
274      *            The key for the keyed digest (must not be null)
275      * @param valueToDigest
276      *            The value (data) which should to digest (maybe empty or null)
277      * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase)
278      * @throws IllegalArgumentException
279      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
280      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(byte[])}
281      */
282     @Deprecated
283     public static String hmacMd5Hex(final byte[] key, final byte[] valueToDigest) {
284         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
285     }
286 
287     /**
288      * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
289      *
290      * @param key
291      *            The key for the keyed digest (must not be null)
292      * @param valueToDigest
293      *            The value (data) which should to digest
294      *            <p>
295      *            The InputStream must not be null and will not be closed
296      *            </p>
297      * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase)
298      * @throws IOException
299      *             If an I/O error occurs.
300      * @throws IllegalArgumentException
301      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
302      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(InputStream)}
303      */
304     @Deprecated
305     public static String hmacMd5Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
306         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
307     }
308 
309     /**
310      * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
311      *
312      * @param key
313      *            The key for the keyed digest (must not be null)
314      * @param valueToDigest
315      *            The value (data) which should to digest (maybe empty or null)
316      * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase)
317      * @throws IllegalArgumentException
318      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
319      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, String).hmacHex(String)}
320      */
321     @Deprecated
322     public static String hmacMd5Hex(final String key, final String valueToDigest) {
323         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
324     }
325 
326     /**
327      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
328      *
329      * @param key
330      *            The key for the keyed digest (must not be null)
331      * @param valueToDigest
332      *            The value (data) which should to digest (maybe empty or null)
333      * @return HmacSHA1 MAC for the given key and value
334      * @throws IllegalArgumentException
335      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
336      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmac(byte[])}
337      */
338     @Deprecated
339     public static byte[] hmacSha1(final byte[] key, final byte[] valueToDigest) {
340         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
341     }
342 
343     /**
344      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
345      *
346      * @param key
347      *            The key for the keyed digest (must not be null)
348      * @param valueToDigest
349      *            The value (data) which should to digest
350      *            <p>
351      *            The InputStream must not be null and will not be closed
352      *            </p>
353      * @return HmacSHA1 MAC for the given key and value
354      * @throws IOException
355      *             If an I/O error occurs.
356      * @throws IllegalArgumentException
357      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
358      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmac(InputStream)}
359      */
360     @Deprecated
361     public static byte[] hmacSha1(final byte[] key, final InputStream valueToDigest) throws IOException {
362         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
363     }
364 
365     /**
366      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
367      *
368      * @param key
369      *            The key for the keyed digest (must not be null)
370      * @param valueToDigest
371      *            The value (data) which should to digest (maybe empty or null)
372      * @return HmacSHA1 MAC for the given key and value
373      * @throws IllegalArgumentException
374      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
375      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmac(String)}
376      */
377     @Deprecated
378     public static byte[] hmacSha1(final String key, final String valueToDigest) {
379         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
380     }
381 
382     // hmacSha1
383 
384     /**
385      * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
386      *
387      * @param key
388      *            The key for the keyed digest (must not be null)
389      * @param valueToDigest
390      *            The value (data) which should to digest (maybe empty or null)
391      * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase)
392      * @throws IllegalArgumentException
393      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
394      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(byte[])}
395      */
396     @Deprecated
397     public static String hmacSha1Hex(final byte[] key, final byte[] valueToDigest) {
398         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
399     }
400 
401     /**
402      * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
403      *
404      * @param key
405      *            The key for the keyed digest (must not be null)
406      * @param valueToDigest
407      *            The value (data) which should to digest
408      *            <p>
409      *            The InputStream must not be null and will not be closed
410      *            </p>
411      * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase)
412      * @throws IOException
413      *             If an I/O error occurs.
414      * @throws IllegalArgumentException
415      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
416      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(InputStream)}
417      */
418     @Deprecated
419     public static String hmacSha1Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
420         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
421     }
422 
423     /**
424      * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
425      *
426      * @param key
427      *            The key for the keyed digest (must not be null)
428      * @param valueToDigest
429      *            The value (data) which should to digest (maybe empty or null)
430      * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase)
431      * @throws IllegalArgumentException
432      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
433      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmacHex(String)}
434      */
435     @Deprecated
436     public static String hmacSha1Hex(final String key, final String valueToDigest) {
437         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
438     }
439 
440     /**
441      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
442      *
443      * @param key
444      *            The key for the keyed digest (must not be null)
445      * @param valueToDigest
446      *            The value (data) which should to digest (maybe empty or null)
447      * @return HmacSHA256 MAC for the given key and value
448      * @throws IllegalArgumentException
449      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
450      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(byte[])}
451      */
452     @Deprecated
453     public static byte[] hmacSha256(final byte[] key, final byte[] valueToDigest) {
454         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
455     }
456 
457     /**
458      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
459      *
460      * @param key
461      *            The key for the keyed digest (must not be null)
462      * @param valueToDigest
463      *            The value (data) which should to digest
464      *            <p>
465      *            The InputStream must not be null and will not be closed
466      *            </p>
467      * @return HmacSHA256 MAC for the given key and value
468      * @throws IOException
469      *             If an I/O error occurs.
470      * @throws IllegalArgumentException
471      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
472      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(InputStream)}
473      */
474     @Deprecated
475     public static byte[] hmacSha256(final byte[] key, final InputStream valueToDigest) throws IOException {
476         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
477     }
478 
479     /**
480      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
481      *
482      * @param key
483      *            The key for the keyed digest (must not be null)
484      * @param valueToDigest
485      *            The value (data) which should to digest (maybe empty or null)
486      * @return HmacSHA256 MAC for the given key and value
487      * @throws IllegalArgumentException
488      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
489      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmac(String)}
490      */
491     @Deprecated
492     public static byte[] hmacSha256(final String key, final String valueToDigest) {
493         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
494     }
495 
496     /**
497      * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
498      *
499      * @param key
500      *            The key for the keyed digest (must not be null)
501      * @param valueToDigest
502      *            The value (data) which should to digest (maybe empty or null)
503      * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase)
504      * @throws IllegalArgumentException
505      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
506      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(byte[])}
507      */
508     @Deprecated
509     public static String hmacSha256Hex(final byte[] key, final byte[] valueToDigest) {
510         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
511     }
512 
513     /**
514      * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
515      *
516      * @param key
517      *            The key for the keyed digest (must not be null)
518      * @param valueToDigest
519      *            The value (data) which should to digest
520      *            <p>
521      *            The InputStream must not be null and will not be closed
522      *            </p>
523      * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase)
524      * @throws IOException
525      *             If an I/O error occurs.
526      * @throws IllegalArgumentException
527      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
528      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(InputStream)}
529      */
530     @Deprecated
531     public static String hmacSha256Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
532         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
533     }
534 
535     /**
536      * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
537      *
538      * @param key
539      *            The key for the keyed digest (must not be null)
540      * @param valueToDigest
541      *            The value (data) which should to digest (maybe empty or null)
542      * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase)
543      * @throws IllegalArgumentException
544      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
545      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmacHex(String)}
546      */
547     @Deprecated
548     public static String hmacSha256Hex(final String key, final String valueToDigest) {
549         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
550     }
551 
552     /**
553      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
554      *
555      * @param key
556      *            The key for the keyed digest (must not be null)
557      * @param valueToDigest
558      *            The value (data) which should to digest (maybe empty or null)
559      * @return HmacSHA384 MAC for the given key and value
560      * @throws IllegalArgumentException
561      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
562      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(byte[])}
563      */
564     @Deprecated
565     public static byte[] hmacSha384(final byte[] key, final byte[] valueToDigest) {
566         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
567     }
568 
569     /**
570      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
571      *
572      * @param key
573      *            The key for the keyed digest (must not be null)
574      * @param valueToDigest
575      *            The value (data) which should to digest
576      *            <p>
577      *            The InputStream must not be null and will not be closed
578      *            </p>
579      * @return HmacSHA384 MAC for the given key and value
580      * @throws IOException
581      *             If an I/O error occurs.
582      * @throws IllegalArgumentException
583      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
584      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(InputStream)}
585      */
586     @Deprecated
587     public static byte[] hmacSha384(final byte[] key, final InputStream valueToDigest) throws IOException {
588         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
589     }
590 
591     /**
592      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
593      *
594      * @param key
595      *            The 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, String).hmac(String)}
602      */
603     @Deprecated
604     public static byte[] hmacSha384(final String key, final String valueToDigest) {
605         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
606     }
607 
608     // hmacSha384
609 
610     /**
611      * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
612      *
613      * @param key
614      *            The key for the keyed digest (must not be null)
615      * @param valueToDigest
616      *            The value (data) which should to digest (maybe empty or null)
617      * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase)
618      * @throws IllegalArgumentException
619      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
620      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(byte[])}
621      */
622     @Deprecated
623     public static String hmacSha384Hex(final byte[] key, final byte[] valueToDigest) {
624         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
625     }
626 
627     /**
628      * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
629      *
630      * @param key
631      *            The key for the keyed digest (must not be null)
632      * @param valueToDigest
633      *            The value (data) which should to digest
634      *            <p>
635      *            The InputStream must not be null and will not be closed
636      *            </p>
637      * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase)
638      * @throws IOException
639      *             If an I/O error occurs.
640      * @throws IllegalArgumentException
641      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
642      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(InputStream)}
643      */
644     @Deprecated
645     public static String hmacSha384Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
646         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
647     }
648 
649     /**
650      * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
651      *
652      * @param key
653      *            The key for the keyed digest (must not be null)
654      * @param valueToDigest
655      *            The value (data) which should to digest (maybe empty or null)
656      * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase)
657      * @throws IllegalArgumentException
658      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
659      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmacHex(String)}
660      */
661     @Deprecated
662     public static String hmacSha384Hex(final String key, final String valueToDigest) {
663         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
664     }
665 
666     /**
667      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
668      *
669      * @param key
670      *            The key for the keyed digest (must not be null)
671      * @param valueToDigest
672      *            The value (data) which should to digest (maybe empty or null)
673      * @return HmacSHA512 MAC for the given key and value
674      * @throws IllegalArgumentException
675      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
676      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(byte[])}
677      */
678     @Deprecated
679     public static byte[] hmacSha512(final byte[] key, final byte[] valueToDigest) {
680         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
681     }
682 
683     /**
684      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
685      *
686      * @param key
687      *            The key for the keyed digest (must not be null)
688      * @param valueToDigest
689      *            The value (data) which should to digest
690      *            <p>
691      *            The InputStream must not be null and will not be closed
692      *            </p>
693      * @return HmacSHA512 MAC for the given key and value
694      * @throws IOException
695      *             If an I/O error occurs.
696      * @throws IllegalArgumentException
697      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
698      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(InputStream)}
699      */
700     @Deprecated
701     public static byte[] hmacSha512(final byte[] key, final InputStream valueToDigest) throws IOException {
702         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
703     }
704 
705     /**
706      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
707      *
708      * @param key
709      *            The 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, String).hmac(String)}
716      */
717     @Deprecated
718     public static byte[] hmacSha512(final String key, final String valueToDigest) {
719         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
720     }
721 
722     // hmacSha512
723 
724     /**
725      * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
726      *
727      * @param key
728      *            The key for the keyed digest (must not be null)
729      * @param valueToDigest
730      *            The value (data) which should to digest (maybe empty or null)
731      * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase)
732      * @throws IllegalArgumentException
733      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
734      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(byte[])}
735      */
736     @Deprecated
737     public static String hmacSha512Hex(final byte[] key, final byte[] valueToDigest) {
738         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
739     }
740 
741     /**
742      * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
743      *
744      * @param key
745      *            The key for the keyed digest (must not be null)
746      * @param valueToDigest
747      *            The value (data) which should to digest
748      *            <p>
749      *            The InputStream must not be null and will not be closed
750      *            </p>
751      * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase)
752      * @throws IOException
753      *             If an I/O error occurs.
754      * @throws IllegalArgumentException
755      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
756      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(InputStream)}
757      */
758     @Deprecated
759     public static String hmacSha512Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
760         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
761     }
762 
763     /**
764      * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
765      *
766      * @param key
767      *            The key for the keyed digest (must not be null)
768      * @param valueToDigest
769      *            The value (data) which should to digest (maybe empty or null)
770      * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase)
771      * @throws IllegalArgumentException
772      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
773      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmacHex(String)}
774      */
775     @Deprecated
776     public static String hmacSha512Hex(final String key, final String valueToDigest) {
777         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
778     }
779 
780     /**
781      * Returns whether this algorithm is available
782      *
783      * @param name the name to check
784      * @return whether this algorithm is available
785      * @since 1.11
786      */
787     public static boolean isAvailable(final HmacAlgorithms name) {
788         try {
789             Mac.getInstance(name.getName());
790             return true;
791         } catch (final NoSuchAlgorithmException e) {
792             return false;
793         }
794     }
795 
796     /**
797      * Returns whether this algorithm is available
798      *
799      * @param name the name to check
800      * @return whether this algorithm is available
801      * @since 1.11
802      */
803     public static boolean isAvailable(final String name) {
804         try {
805             Mac.getInstance(name);
806             return true;
807         } catch (final NoSuchAlgorithmException e) {
808             return false;
809         }
810     }
811 
812     /**
813      * Resets and then updates the given {@link Mac} with the value.
814      *
815      * @param mac
816      *            the initialized {@link Mac} to update
817      * @param valueToDigest
818      *            the value to update the {@link Mac} with (maybe null or empty)
819      * @return the updated {@link Mac}
820      * @throws IllegalStateException
821      *             if the Mac was not initialized
822      */
823     public static Mac updateHmac(final Mac mac, final byte[] valueToDigest) {
824         mac.reset();
825         mac.update(valueToDigest);
826         return mac;
827     }
828 
829     /**
830      * Resets and then updates the given {@link Mac} with the value.
831      *
832      * @param mac
833      *            the initialized {@link Mac} to update
834      * @param valueToDigest
835      *            the value to update the {@link Mac} with
836      *            <p>
837      *            The InputStream must not be null and will not be closed
838      *            </p>
839      * @return the updated {@link Mac}
840      * @throws IOException
841      *             If an I/O error occurs.
842      * @throws IllegalStateException
843      *             If the Mac was not initialized
844      */
845     public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException {
846         mac.reset();
847         final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
848         int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
849 
850         while (read > -1) {
851             mac.update(buffer, 0, read);
852             read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
853         }
854 
855         return mac;
856     }
857 
858     /**
859      * Resets and then updates the given {@link Mac} with the value.
860      *
861      * @param mac
862      *            the initialized {@link Mac} to update
863      * @param valueToDigest
864      *            the value to update the {@link Mac} with (maybe null or empty)
865      * @return the updated {@link Mac}
866      * @throws IllegalStateException
867      *             if the Mac was not initialized
868      */
869     public static Mac updateHmac(final Mac mac, final String valueToDigest) {
870         mac.reset();
871         mac.update(StringUtils.getBytesUtf8(valueToDigest));
872         return mac;
873     }
874 
875     private final Mac mac;
876 
877     /**
878      * Preserves binary compatibility only.
879      * As for previous versions does not provide useful behavior
880      * @deprecated since 1.11; only useful to preserve binary compatibility
881      */
882     @Deprecated
883     public HmacUtils() {
884         this(null);
885     }
886 
887     /**
888      * Creates an instance using the provided algorithm type.
889      *
890      * @param algorithm to use.
891      * @param key the key to use
892      * @throws IllegalArgumentException
893      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
894      * @since 1.11
895      */
896     public HmacUtils(final HmacAlgorithms algorithm, final byte[] key) {
897         this(algorithm.getName(), key);
898     }
899 
900     /**
901      * Creates an instance using the provided algorithm type.
902      *
903      * @param algorithm to use
904      * @param  key the key to use
905      * @throws IllegalArgumentException
906      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
907      * @since 1.11
908      */
909     public HmacUtils(final HmacAlgorithms algorithm, final String key) {
910         this(algorithm.getName(), StringUtils.getBytesUtf8(key));
911     }
912 
913     private HmacUtils(final Mac mac) {
914         this.mac = mac;
915     }
916 
917     /**
918      * Creates an instance using the provided algorithm type.
919      *
920      * @param algorithm to use
921      * @param  key the key to use
922      * @throws IllegalArgumentException
923      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
924      * @since 1.11
925      */
926     public HmacUtils(final String algorithm, final byte[] key) {
927         this(getInitializedMac(algorithm, key));
928     }
929 
930     /**
931      * Creates an instance using the provided algorithm type.
932      *
933      * @param algorithm to use
934      * @param  key the key to use
935      * @throws IllegalArgumentException
936      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
937      * @since 1.11
938      */
939     public HmacUtils(final String algorithm, final String key) {
940         this(algorithm, StringUtils.getBytesUtf8(key));
941     }
942 
943     /**
944      * Returns the digest for the input data.
945      *
946      * @param valueToDigest the input to use
947      * @return the digest as a byte[]
948      * @since 1.11
949      */
950     public byte[] hmac(final byte[] valueToDigest) {
951         return mac.doFinal(valueToDigest);
952     }
953 
954     /**
955      * Returns the digest for the input data.
956      *
957      * @param valueToDigest the input to use
958      * @return the digest as a byte[]
959      * @since 1.11
960      */
961     public byte[] hmac(final ByteBuffer valueToDigest) {
962         mac.update(valueToDigest);
963         return mac.doFinal();
964     }
965 
966     /**
967      * Returns the digest for the file.
968      *
969      * @param valueToDigest the file to use
970      * @return the digest
971      * @throws IOException
972      *             If an I/O error occurs.
973      * @since 1.11
974      */
975     public byte[] hmac(final File valueToDigest) throws IOException {
976         try (final BufferedInputStream stream = new BufferedInputStream(new FileInputStream(valueToDigest))) {
977             return hmac(stream);
978         }
979     }
980 
981     /**
982      * Returns the digest for the stream.
983      *
984      * @param valueToDigest
985      *            the data to use
986      *            <p>
987      *            The InputStream must not be null and will not be closed
988      *            </p>
989      * @return the digest
990      * @throws IOException
991      *             If an I/O error occurs.
992      * @since 1.11
993      */
994     public byte[] hmac(final InputStream valueToDigest) throws IOException {
995         final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
996         int read;
997 
998         while ((read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH)) > -1) {
999             mac.update(buffer, 0, read);
1000         }
1001         return mac.doFinal();
1002     }
1003 
1004     /**
1005      * Returns the digest for the input data.
1006      *
1007      * @param valueToDigest the input to use, treated as UTF-8
1008      * @return the digest as a byte[]
1009      * @since 1.11
1010      */
1011     public byte[] hmac(final String valueToDigest) {
1012         return mac.doFinal(StringUtils.getBytesUtf8(valueToDigest));
1013     }
1014 
1015     /**
1016      * Returns the digest for the input data.
1017      *
1018      * @param valueToDigest the input to use
1019      * @return the digest as a hexadecimal String
1020      * @since 1.11
1021      */
1022     public String hmacHex(final byte[] valueToDigest) {
1023         return Hex.encodeHexString(hmac(valueToDigest));
1024     }
1025 
1026     /**
1027      * Returns the digest for the input data.
1028      *
1029      * @param valueToDigest the input to use
1030      * @return the digest as a hexadecimal String
1031      * @since 1.11
1032      */
1033     public String hmacHex(final ByteBuffer valueToDigest) {
1034         return Hex.encodeHexString(hmac(valueToDigest));
1035     }
1036 
1037     /**
1038      * Returns the digest for the file.
1039      *
1040      * @param valueToDigest the file to use
1041      * @return the digest as a hexadecimal String
1042      * @throws IOException
1043      *             If an I/O error occurs.
1044      * @since 1.11
1045      */
1046     public String hmacHex(final File valueToDigest) throws IOException {
1047         return Hex.encodeHexString(hmac(valueToDigest));
1048     }
1049 
1050     /**
1051      * Returns the digest for the stream.
1052      *
1053      * @param valueToDigest
1054      *            the data to use
1055      *            <p>
1056      *            The InputStream must not be null and will not be closed
1057      *            </p>
1058      * @return the digest as a hexadecimal String
1059      * @throws IOException
1060      *             If an I/O error occurs.
1061      * @since 1.11
1062      */
1063     public String hmacHex(final InputStream valueToDigest) throws IOException {
1064         return Hex.encodeHexString(hmac(valueToDigest));
1065     }
1066 
1067     /**
1068      * Returns the digest for the input data.
1069      *
1070      * @param valueToDigest the input to use, treated as UTF-8
1071      * @return the digest as a hexadecimal String
1072      * @since 1.11
1073      */
1074     public String hmacHex(final String valueToDigest) {
1075         return Hex.encodeHexString(hmac(valueToDigest));
1076     }
1077 
1078 }