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