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