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