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