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