View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.codec.digest;
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.security.InvalidKeyException;
23  import java.security.Key;
24  import java.security.NoSuchAlgorithmException;
25  
26  import javax.crypto.Mac;
27  import javax.crypto.spec.SecretKeySpec;
28  
29  import org.apache.commons.codec.binary.Hex;
30  import org.apache.commons.codec.binary.StringUtils;
31  
32  /**
33   * Simplifies common {@link javax.crypto.Mac} tasks. This class is immutable and thread-safe.
34   *
35   *
36   * <p>
37   * <strong>Note: Not all JCE implementations supports all algorithms. If not supported, an IllegalArgumentException is
38   * thrown.</strong>
39   * </p>
40   *
41   * @since 1.10
42   * @version $Id: HmacUtils.html 928559 2014-11-10 02:53:54Z ggregory $
43   */
44  public final class HmacUtils {
45  
46      private static final int STREAM_BUFFER_LENGTH = 1024;
47  
48      /**
49       * Returns an initialized <code>Mac</code> for the HmacMD5 algorithm.
50       * <p>
51       * Every implementation of the Java platform is required to support this standard Mac algorithm.
52       * </p>
53       *
54       * @param key
55       *            They key for the keyed digest (must not be null)
56       * @return A Mac instance initialized with the given key.
57       * @see Mac#getInstance(String)
58       * @see Mac#init(Key)
59       * @throws IllegalArgumentException
60       *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
61       */
62      public static Mac getHmacMd5(final byte[] key) {
63          return getInitializedMac(HmacAlgorithms.HMAC_MD5, key);
64      }
65  
66      /**
67       * Returns an initialized <code>Mac</code> for the HmacSHA1 algorithm.
68       * <p>
69       * Every implementation of the Java platform is required to support this standard Mac algorithm.
70       * </p>
71       *
72       * @param key
73       *            They key for the keyed digest (must not be null)
74       * @return A Mac instance initialized with the given key.
75       * @see Mac#getInstance(String)
76       * @see Mac#init(Key)
77       * @throws IllegalArgumentException
78       *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
79       */
80      public static Mac getHmacSha1(final byte[] key) {
81          return getInitializedMac(HmacAlgorithms.HMAC_SHA_1, key);
82      }
83  
84      /**
85       * Returns an initialized <code>Mac</code> for the HmacSHA256 algorithm.
86       * <p>
87       * Every implementation of the Java platform is required to support this standard Mac algorithm.
88       * </p>
89       *
90       * @param key
91       *            They key for the keyed digest (must not be null)
92       * @return A Mac instance initialized with the given key.
93       * @see Mac#getInstance(String)
94       * @see Mac#init(Key)
95       * @throws IllegalArgumentException
96       *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
97       */
98      public static Mac getHmacSha256(final byte[] key) {
99          return getInitializedMac(HmacAlgorithms.HMAC_SHA_256, key);
100     }
101 
102     /**
103      * Returns an initialized <code>Mac</code> for the HmacSHA384 algorithm.
104      * <p>
105      * Every implementation of the Java platform is <em>not</em> required to support this Mac algorithm.
106      * </p>
107      *
108      * @param key
109      *            They 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      */
116     public static Mac getHmacSha384(final byte[] key) {
117         return getInitializedMac(HmacAlgorithms.HMAC_SHA_384, key);
118     }
119 
120     /**
121      * Returns an initialized <code>Mac</code> for the HmacSHA512 algorithm.
122      * <p>
123      * Every implementation of the Java platform is <em>not</em> required to support this Mac algorithm.
124      * </p>
125      *
126      * @param key
127      *            They key for the keyed digest (must not be null)
128      * @return A Mac instance initialized with the given key.
129      * @see Mac#getInstance(String)
130      * @see Mac#init(Key)
131      * @throws IllegalArgumentException
132      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
133      */
134     public static Mac getHmacSha512(final byte[] key) {
135         return getInitializedMac(HmacAlgorithms.HMAC_SHA_512, key);
136     }
137 
138     /**
139      * Returns an initialized <code>Mac</code> for the given <code>algorithm</code>.
140      *
141      * @param algorithm
142      *            the name of the algorithm requested. See <a href=
143      *            "http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA" >Appendix
144      *            A in the Java Cryptography Architecture Reference Guide</a> for information about standard algorithm
145      *            names.
146      * @param key
147      *            They key for the keyed digest (must not be null)
148      * @return A Mac instance initialized with the given key.
149      * @see Mac#getInstance(String)
150      * @see Mac#init(Key)
151      * @throws IllegalArgumentException
152      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
153      */
154     public static Mac getInitializedMac(final HmacAlgorithms algorithm, final byte[] key) {
155         return getInitializedMac(algorithm.toString(), key);
156     }
157 
158     /**
159      * Returns an initialized <code>Mac</code> for the given <code>algorithm</code>.
160      *
161      * @param algorithm
162      *            the name of the algorithm requested. See <a href=
163      *            "http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA" >Appendix
164      *            A in the Java Cryptography Architecture Reference Guide</a> for information about standard algorithm
165      *            names.
166      * @param key
167      *            They key for the keyed digest (must not be null)
168      * @return A Mac instance initialized with the given key.
169      * @see Mac#getInstance(String)
170      * @see Mac#init(Key)
171      * @throws IllegalArgumentException
172      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
173      */
174     public static Mac getInitializedMac(final String algorithm, final byte[] key) {
175 
176         if (key == null) {
177             throw new IllegalArgumentException("Null key");
178         }
179 
180         try {
181             final SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
182             final Mac mac = Mac.getInstance(algorithm);
183             mac.init(keySpec);
184             return mac;
185         } catch (final NoSuchAlgorithmException e) {
186             throw new IllegalArgumentException(e);
187         } catch (final InvalidKeyException e) {
188             throw new IllegalArgumentException(e);
189         }
190     }
191 
192     // hmacMd5
193 
194     /**
195      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
196      *
197      * @param key
198      *            They key for the keyed digest (must not be null)
199      * @param valueToDigest
200      *            The value (data) which should to digest (maybe empty or null)
201      * @return HmacMD5 MAC for the given key and value
202      * @throws IllegalArgumentException
203      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
204      */
205     public static byte[] hmacMd5(final byte[] key, final byte[] valueToDigest) {
206         try {
207             return getHmacMd5(key).doFinal(valueToDigest);
208         } catch (final IllegalStateException e) {
209             // cannot happen
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      *            They key for the keyed digest (must not be null)
219      * @param valueToDigest
220      *            The value (data) which should to digest
221      *            <p>
222      *            The InputStream must not be null and will not be closed
223      *            </p>
224      * @return HmacMD5 MAC for the given key and value
225      * @throws IOException
226      *             If an I/O error occurs.
227      * @throws IllegalArgumentException
228      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
229      */
230     public static byte[] hmacMd5(final byte[] key, final InputStream valueToDigest) throws IOException {
231         return updateHmac(getHmacMd5(key), valueToDigest).doFinal();
232     }
233 
234     /**
235      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
236      *
237      * @param key
238      *            They key for the keyed digest (must not be null)
239      * @param valueToDigest
240      *            The value (data) which should to digest (maybe empty or null)
241      * @return HmacMD5 MAC for the given key and value
242      * @throws IllegalArgumentException
243      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
244      */
245     public static byte[] hmacMd5(final String key, final String valueToDigest) {
246         return hmacMd5(StringUtils.getBytesUtf8(key), StringUtils.getBytesUtf8(valueToDigest));
247     }
248 
249     /**
250      * Returns a HmacMD5 Message Authentication Code (MAC) as a hex string (lowercase) for the given key and value.
251      *
252      * @param key
253      *            They key for the keyed digest (must not be null)
254      * @param valueToDigest
255      *            The value (data) which should to digest (maybe empty or null)
256      * @return HmacMD5 MAC for the given key and value as a hex string (lowercase)
257      * @throws IllegalArgumentException
258      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
259      */
260     public static String hmacMd5Hex(final byte[] key, final byte[] valueToDigest) {
261         return Hex.encodeHexString(hmacMd5(key, valueToDigest));
262     }
263 
264     /**
265      * Returns a HmacMD5 Message Authentication Code (MAC) as a hex string (lowercase) for the given key and value.
266      *
267      * @param key
268      *            They key for the keyed digest (must not be null)
269      * @param valueToDigest
270      *            The value (data) which should to digest
271      *            <p>
272      *            The InputStream must not be null and will not be closed
273      *            </p>
274      * @return HmacMD5 MAC for the given key and value as a hex string (lowercase)
275      * @throws IOException
276      *             If an I/O error occurs.
277      * @throws IllegalArgumentException
278      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
279      */
280     public static String hmacMd5Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
281         return Hex.encodeHexString(hmacMd5(key, valueToDigest));
282     }
283 
284     /**
285      * Returns a HmacMD5 Message Authentication Code (MAC) as a hex string (lowercase) for the given key and value.
286      *
287      * @param key
288      *            They key for the keyed digest (must not be null)
289      * @param valueToDigest
290      *            The value (data) which should to digest (maybe empty or null)
291      * @return HmacMD5 MAC for the given key and value as a hex string (lowercase)
292      * @throws IllegalArgumentException
293      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
294      */
295     public static String hmacMd5Hex(final String key, final String valueToDigest) {
296         return Hex.encodeHexString(hmacMd5(key, valueToDigest));
297     }
298 
299     // hmacSha1
300 
301     /**
302      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
303      *
304      * @param key
305      *            They key for the keyed digest (must not be null)
306      * @param valueToDigest
307      *            The value (data) which should to digest (maybe empty or null)
308      * @return HmacSHA1 MAC for the given key and value
309      * @throws IllegalArgumentException
310      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
311      */
312     public static byte[] hmacSha1(final byte[] key, final byte[] valueToDigest) {
313         try {
314             return getHmacSha1(key).doFinal(valueToDigest);
315         } catch (final IllegalStateException e) {
316             // cannot happen
317             throw new IllegalArgumentException(e);
318         }
319     }
320 
321     /**
322      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
323      *
324      * @param key
325      *            They key for the keyed digest (must not be null)
326      * @param valueToDigest
327      *            The value (data) which should to digest
328      *            <p>
329      *            The InputStream must not be null and will not be closed
330      *            </p>
331      * @return HmacSHA1 MAC for the given key and value
332      * @throws IOException
333      *             If an I/O error occurs.
334      * @throws IllegalArgumentException
335      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
336      */
337     public static byte[] hmacSha1(final byte[] key, final InputStream valueToDigest) throws IOException {
338         return updateHmac(getHmacSha1(key), valueToDigest).doFinal();
339     }
340 
341     /**
342      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
343      *
344      * @param key
345      *            They key for the keyed digest (must not be null)
346      * @param valueToDigest
347      *            The value (data) which should to digest (maybe empty or null)
348      * @return HmacSHA1 MAC for the given key and value
349      * @throws IllegalArgumentException
350      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
351      */
352     public static byte[] hmacSha1(final String key, final String valueToDigest) {
353         return hmacSha1(StringUtils.getBytesUtf8(key), StringUtils.getBytesUtf8(valueToDigest));
354     }
355 
356     /**
357      * Returns a HmacSHA1 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
358      *
359      * @param key
360      *            They key for the keyed digest (must not be null)
361      * @param valueToDigest
362      *            The value (data) which should to digest (maybe empty or null)
363      * @return HmacSHA1 MAC for the given key and value as hex string (lowercase)
364      * @throws IllegalArgumentException
365      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
366      */
367     public static String hmacSha1Hex(final byte[] key, final byte[] valueToDigest) {
368         return Hex.encodeHexString(hmacSha1(key, valueToDigest));
369     }
370 
371     /**
372      * Returns a HmacSHA1 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
373      *
374      * @param key
375      *            They key for the keyed digest (must not be null)
376      * @param valueToDigest
377      *            The value (data) which should to digest
378      *            <p>
379      *            The InputStream must not be null and will not be closed
380      *            </p>
381      * @return HmacSHA1 MAC for the given key and value as hex string (lowercase)
382      * @throws IOException
383      *             If an I/O error occurs.
384      * @throws IllegalArgumentException
385      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
386      */
387     public static String hmacSha1Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
388         return Hex.encodeHexString(hmacSha1(key, valueToDigest));
389     }
390 
391     /**
392      * Returns a HmacSHA1 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
393      *
394      * @param key
395      *            They key for the keyed digest (must not be null)
396      * @param valueToDigest
397      *            The value (data) which should to digest (maybe empty or null)
398      * @return HmacSHA1 MAC for the given key and value as hex string (lowercase)
399      * @throws IllegalArgumentException
400      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
401      */
402     public static String hmacSha1Hex(final String key, final String valueToDigest) {
403         return Hex.encodeHexString(hmacSha1(key, valueToDigest));
404     }
405 
406     // hmacSha256
407 
408     /**
409      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
410      *
411      * @param key
412      *            They key for the keyed digest (must not be null)
413      * @param valueToDigest
414      *            The value (data) which should to digest (maybe empty or null)
415      * @return HmacSHA256 MAC for the given key and value
416      * @throws IllegalArgumentException
417      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
418      */
419     public static byte[] hmacSha256(final byte[] key, final byte[] valueToDigest) {
420         try {
421             return getHmacSha256(key).doFinal(valueToDigest);
422         } catch (final IllegalStateException e) {
423             // cannot happen
424             throw new IllegalArgumentException(e);
425         }
426     }
427 
428     /**
429      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
430      *
431      * @param key
432      *            They key for the keyed digest (must not be null)
433      * @param valueToDigest
434      *            The value (data) which should to digest
435      *            <p>
436      *            The InputStream must not be null and will not be closed
437      *            </p>
438      * @return HmacSHA256 MAC for the given key and value
439      * @throws IOException
440      *             If an I/O error occurs.
441 s     * @throws IllegalArgumentException
442      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
443      */
444     public static byte[] hmacSha256(final byte[] key, final InputStream valueToDigest) throws IOException {
445         return updateHmac(getHmacSha256(key), valueToDigest).doFinal();
446     }
447 
448     /**
449      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
450      *
451      * @param key
452      *            They key for the keyed digest (must not be null)
453      * @param valueToDigest
454      *            The value (data) which should to digest (maybe empty or null)
455      * @return HmacSHA256 MAC for the given key and value
456      * @throws IllegalArgumentException
457      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
458      */
459     public static byte[] hmacSha256(final String key, final String valueToDigest) {
460         return hmacSha256(StringUtils.getBytesUtf8(key), StringUtils.getBytesUtf8(valueToDigest));
461     }
462 
463     /**
464      * Returns a HmacSHA256 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
465      *
466      * @param key
467      *            They key for the keyed digest (must not be null)
468      * @param valueToDigest
469      *            The value (data) which should to digest (maybe empty or null)
470      * @return HmacSHA256 MAC for the given key and value as hex string (lowercase)
471      * @throws IllegalArgumentException
472      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
473      */
474     public static String hmacSha256Hex(final byte[] key, final byte[] valueToDigest) {
475         return Hex.encodeHexString(hmacSha256(key, valueToDigest));
476     }
477 
478     /**
479      * Returns a HmacSHA256 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
480      *
481      * @param key
482      *            They key for the keyed digest (must not be null)
483      * @param valueToDigest
484      *            The value (data) which should to digest
485      *            <p>
486      *            The InputStream must not be null and will not be closed
487      *            </p>
488      * @return HmacSHA256 MAC for the given key and value as hex string (lowercase)
489      * @throws IOException
490      *             If an I/O error occurs.
491      * @throws IllegalArgumentException
492      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
493      */
494     public static String hmacSha256Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
495         return Hex.encodeHexString(hmacSha256(key, valueToDigest));
496     }
497 
498     /**
499      * Returns a HmacSHA256 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
500      *
501      * @param key
502      *            They key for the keyed digest (must not be null)
503      * @param valueToDigest
504      *            The value (data) which should to digest (maybe empty or null)
505      * @return HmacSHA256 MAC for the given key and value as hex string (lowercase)
506      * @throws IllegalArgumentException
507      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
508      */
509     public static String hmacSha256Hex(final String key, final String valueToDigest) {
510         return Hex.encodeHexString(hmacSha256(key, valueToDigest));
511     }
512 
513     // hmacSha384
514 
515     /**
516      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
517      *
518      * @param key
519      *            They key for the keyed digest (must not be null)
520      * @param valueToDigest
521      *            The value (data) which should to digest (maybe empty or null)
522      * @return HmacSHA384 MAC for the given key and value
523      * @throws IllegalArgumentException
524      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
525      */
526     public static byte[] hmacSha384(final byte[] key, final byte[] valueToDigest) {
527         try {
528             return getHmacSha384(key).doFinal(valueToDigest);
529         } catch (final IllegalStateException e) {
530             // cannot happen
531             throw new IllegalArgumentException(e);
532         }
533     }
534 
535     /**
536      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
537      *
538      * @param key
539      *            They key for the keyed digest (must not be null)
540      * @param valueToDigest
541      *            The value (data) which should to digest
542      *            <p>
543      *            The InputStream must not be null and will not be closed
544      *            </p>
545      * @return HmacSHA384 MAC for the given key and value
546      * @throws IOException
547      *             If an I/O error occurs.
548      * @throws IllegalArgumentException
549      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
550      */
551     public static byte[] hmacSha384(final byte[] key, final InputStream valueToDigest) throws IOException {
552         return updateHmac(getHmacSha384(key), valueToDigest).doFinal();
553     }
554 
555     /**
556      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
557      *
558      * @param key
559      *            They key for the keyed digest (must not be null)
560      * @param valueToDigest
561      *            The value (data) which should to digest (maybe empty or null)
562      * @return HmacSHA384 MAC for the given key and value
563      * @throws IllegalArgumentException
564      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
565      */
566     public static byte[] hmacSha384(final String key, final String valueToDigest) {
567         return hmacSha384(StringUtils.getBytesUtf8(key), StringUtils.getBytesUtf8(valueToDigest));
568     }
569 
570     /**
571      * Returns a HmacSHA384 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
572      *
573      * @param key
574      *            They key for the keyed digest (must not be null)
575      * @param valueToDigest
576      *            The value (data) which should to digest (maybe empty or null)
577      * @return HmacSHA384 MAC for the given key and value as hex string (lowercase)
578      * @throws IllegalArgumentException
579      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
580      */
581     public static String hmacSha384Hex(final byte[] key, final byte[] valueToDigest) {
582         return Hex.encodeHexString(hmacSha384(key, valueToDigest));
583     }
584 
585     /**
586      * Returns a HmacSHA384 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
587      *
588      * @param key
589      *            They key for the keyed digest (must not be null)
590      * @param valueToDigest
591      *            The value (data) which should to digest
592      *            <p>
593      *            The InputStream must not be null and will not be closed
594      *            </p>
595      * @return HmacSHA384 MAC for the given key and value as hex string (lowercase)
596      * @throws IOException
597      *             If an I/O error occurs.
598      * @throws IllegalArgumentException
599      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
600      */
601     public static String hmacSha384Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
602         return Hex.encodeHexString(hmacSha384(key, valueToDigest));
603     }
604 
605     /**
606      * Returns a HmacSHA384 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
607      *
608      * @param key
609      *            They key for the keyed digest (must not be null)
610      * @param valueToDigest
611      *            The value (data) which should to digest (maybe empty or null)
612      * @return HmacSHA384 MAC for the given key and value as hex string (lowercase)
613      * @throws IllegalArgumentException
614      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
615      */
616     public static String hmacSha384Hex(final String key, final String valueToDigest) {
617         return Hex.encodeHexString(hmacSha384(key, valueToDigest));
618     }
619 
620     // hmacSha512
621 
622     /**
623      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
624      *
625      * @param key
626      *            They key for the keyed digest (must not be null)
627      * @param valueToDigest
628      *            The value (data) which should to digest (maybe empty or null)
629      * @return HmacSHA512 MAC for the given key and value
630      * @throws IllegalArgumentException
631      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
632      */
633     public static byte[] hmacSha512(final byte[] key, final byte[] valueToDigest) {
634         try {
635             return getHmacSha512(key).doFinal(valueToDigest);
636         } catch (final IllegalStateException e) {
637             // cannot happen
638             throw new IllegalArgumentException(e);
639         }
640     }
641 
642     /**
643      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
644      *
645      * @param key
646      *            They key for the keyed digest (must not be null)
647      * @param valueToDigest
648      *            The value (data) which should to digest
649      *            <p>
650      *            The InputStream must not be null and will not be closed
651      *            </p>
652      * @return HmacSHA512 MAC for the given key and value
653      * @throws IOException
654      *             If an I/O error occurs.
655      * @throws IllegalArgumentException
656      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
657      */
658     public static byte[] hmacSha512(final byte[] key, final InputStream valueToDigest) throws IOException {
659         return updateHmac(getHmacSha512(key), valueToDigest).doFinal();
660     }
661 
662     /**
663      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
664      *
665      * @param key
666      *            They key for the keyed digest (must not be null)
667      * @param valueToDigest
668      *            The value (data) which should to digest (maybe empty or null)
669      * @return HmacSHA512 MAC for the given key and value
670      * @throws IllegalArgumentException
671      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
672      */
673     public static byte[] hmacSha512(final String key, final String valueToDigest) {
674         return hmacSha512(StringUtils.getBytesUtf8(key), StringUtils.getBytesUtf8(valueToDigest));
675     }
676 
677     /**
678      * Returns a HmacSHA512 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
679      *
680      * @param key
681      *            They key for the keyed digest (must not be null)
682      * @param valueToDigest
683      *            The value (data) which should to digest (maybe empty or null)
684      * @return HmacSHA512 MAC for the given key and value as hex string (lowercase)
685      * @throws IllegalArgumentException
686      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
687      */
688     public static String hmacSha512Hex(final byte[] key, final byte[] valueToDigest) {
689         return Hex.encodeHexString(hmacSha512(key, valueToDigest));
690     }
691 
692     /**
693      * Returns a HmacSHA512 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
694      *
695      * @param key
696      *            They key for the keyed digest (must not be null)
697      * @param valueToDigest
698      *            The value (data) which should to digest
699      *            <p>
700      *            The InputStream must not be null and will not be closed
701      *            </p>
702      * @return HmacSHA512 MAC for the given key and value as hex string (lowercase)
703      * @throws IOException
704      *             If an I/O error occurs.
705      * @throws IllegalArgumentException
706      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
707      */
708     public static String hmacSha512Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
709         return Hex.encodeHexString(hmacSha512(key, valueToDigest));
710     }
711 
712     /**
713      * Returns a HmacSHA512 Message Authentication Code (MAC) as hex string (lowercase) for the given key and value.
714      *
715      * @param key
716      *            They key for the keyed digest (must not be null)
717      * @param valueToDigest
718      *            The value (data) which should to digest (maybe empty or null)
719      * @return HmacSHA512 MAC for the given key and value as hex string (lowercase)
720      * @throws IllegalArgumentException
721      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
722      */
723     public static String hmacSha512Hex(final String key, final String valueToDigest) {
724         return Hex.encodeHexString(hmacSha512(key, valueToDigest));
725     }
726 
727     // update
728 
729     /**
730      * Updates the given {@link Mac}. This generates a digest for valueToDigest and the key the Mac was initialized
731      *
732      * @param mac
733      *            the initialized {@link Mac} to update
734      * @param valueToDigest
735      *            the value to update the {@link Mac} with (maybe null or empty)
736      * @return the updated {@link Mac}
737      * @throws IllegalStateException
738      *             if the Mac was not initialized
739      * @since 1.x
740      */
741     public static Mac updateHmac(final Mac mac, final byte[] valueToDigest) {
742         mac.reset();
743         mac.update(valueToDigest);
744         return mac;
745     }
746 
747     /**
748      * Updates the given {@link Mac}. This generates a digest for valueToDigest and the key the Mac was initialized
749      *
750      * @param mac
751      *            the initialized {@link Mac} to update
752      * @param valueToDigest
753      *            the value to update the {@link Mac} with
754      *            <p>
755      *            The InputStream must not be null and will not be closed
756      *            </p>
757      * @return the updated {@link Mac}
758      * @throws IOException
759      *             If an I/O error occurs.
760      * @throws IllegalStateException
761      *             If the Mac was not initialized
762      * @since 1.x
763      */
764     public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException {
765         mac.reset();
766         final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
767         int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
768 
769         while (read > -1) {
770             mac.update(buffer, 0, read);
771             read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
772         }
773 
774         return mac;
775     }
776 
777     /**
778      * Updates the given {@link Mac}. This generates a digest for valueToDigest and the key the Mac was initialized
779      *
780      * @param mac
781      *            the initialized {@link Mac} to update
782      * @param valueToDigest
783      *            the value to update the {@link Mac} with (maybe null or empty)
784      * @return the updated {@link Mac}
785      * @throws IllegalStateException
786      *             if the Mac was not initialized
787      * @since 1.x
788      */
789     public static Mac updateHmac(final Mac mac, final String valueToDigest) {
790         mac.reset();
791         mac.update(StringUtils.getBytesUtf8(valueToDigest));
792         return mac;
793     }
794 }