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