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