001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.codec.digest;
019
020import java.io.IOException;
021import java.io.InputStream;
022import java.security.InvalidKeyException;
023import java.security.Key;
024import java.security.NoSuchAlgorithmException;
025
026import javax.crypto.Mac;
027import javax.crypto.spec.SecretKeySpec;
028
029import org.apache.commons.codec.binary.Hex;
030import org.apache.commons.codec.binary.StringUtils;
031
032/**
033 * Simplifies common {@link javax.crypto.Mac} tasks. This class is immutable and thread-safe.
034 *
035 *
036 * <p>
037 * <strong>Note: Not all JCE implementations supports all algorithms. If not supported, an IllegalArgumentException is
038 * thrown.</strong>
039 * </p>
040 *
041 * @since 1.10
042 * @version $Id: HmacUtils.html 928559 2014-11-10 02:53:54Z ggregory $
043 */
044public final class HmacUtils {
045
046    private static final int STREAM_BUFFER_LENGTH = 1024;
047
048    /**
049     * Returns an initialized <code>Mac</code> for the HmacMD5 algorithm.
050     * <p>
051     * Every implementation of the Java platform is required to support this standard Mac algorithm.
052     * </p>
053     *
054     * @param key
055     *            They key for the keyed digest (must not be null)
056     * @return A Mac instance initialized with the given key.
057     * @see Mac#getInstance(String)
058     * @see Mac#init(Key)
059     * @throws IllegalArgumentException
060     *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
061     */
062    public static Mac getHmacMd5(final byte[] key) {
063        return getInitializedMac(HmacAlgorithms.HMAC_MD5, key);
064    }
065
066    /**
067     * Returns an initialized <code>Mac</code> for the HmacSHA1 algorithm.
068     * <p>
069     * Every implementation of the Java platform is required to support this standard Mac algorithm.
070     * </p>
071     *
072     * @param key
073     *            They key for the keyed digest (must not be null)
074     * @return A Mac instance initialized with the given key.
075     * @see Mac#getInstance(String)
076     * @see Mac#init(Key)
077     * @throws IllegalArgumentException
078     *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
079     */
080    public static Mac getHmacSha1(final byte[] key) {
081        return getInitializedMac(HmacAlgorithms.HMAC_SHA_1, key);
082    }
083
084    /**
085     * Returns an initialized <code>Mac</code> for the HmacSHA256 algorithm.
086     * <p>
087     * Every implementation of the Java platform is required to support this standard Mac algorithm.
088     * </p>
089     *
090     * @param key
091     *            They key for the keyed digest (must not be null)
092     * @return A Mac instance initialized with the given key.
093     * @see Mac#getInstance(String)
094     * @see Mac#init(Key)
095     * @throws IllegalArgumentException
096     *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
097     */
098    public static Mac getHmacSha256(final byte[] key) {
099        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.
441s     * @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}