HmacUtils.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.codec.digest;

  18. import java.io.BufferedInputStream;
  19. import java.io.File;
  20. import java.io.FileInputStream;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.nio.ByteBuffer;
  24. import java.security.InvalidKeyException;
  25. import java.security.Key;
  26. import java.security.NoSuchAlgorithmException;

  27. import javax.crypto.Mac;
  28. import javax.crypto.spec.SecretKeySpec;

  29. import org.apache.commons.codec.binary.Hex;
  30. import org.apache.commons.codec.binary.StringUtils;

  31. /**
  32.  * Simplifies common {@link javax.crypto.Mac} tasks. This class is immutable and thread-safe.
  33.  * However the Mac may not be.
  34.  * <p>
  35.  * <strong>Note: Not all JCE implementations support all algorithms. If not supported, an IllegalArgumentException is
  36.  * thrown.</strong>
  37.  * </p>
  38.  * <p>
  39.  * Sample usage:
  40.  * </p>
  41.  * <pre>
  42.  * import static HmacAlgorithms.*;
  43.  * byte[] key = {1,2,3,4}; // don't use this actual key!
  44.  * String valueToDigest = "The quick brown fox jumps over the lazy dog";
  45.  * byte[] hmac = new HmacUtils(HMAC_SHA_224, key).hmac(valueToDigest);
  46.  * // Mac re-use
  47.  * HmacUtils hm1 = new HmacUtils("HmacAlgoName", key); // use a valid name here!
  48.  * String hexPom = hm1.hmacHex(new File("pom.xml"));
  49.  * String hexNot = hm1.hmacHex(new File("NOTICE.txt"));
  50.  * </pre>
  51.  * @since 1.10
  52.  */
  53. public final class HmacUtils {

  54.     private static final int STREAM_BUFFER_LENGTH = 1024;

  55.     /**
  56.      * Returns an initialized {@code Mac} for the HmacMD5 algorithm.
  57.      * <p>
  58.      * Every implementation of the Java platform is required to support this standard Mac algorithm.
  59.      * </p>
  60.      *
  61.      * @param key
  62.      *            The key for the keyed digest (must not be null)
  63.      * @return A Mac instance initialized with the given key.
  64.      * @see Mac#getInstance(String)
  65.      * @see Mac#init(Key)
  66.      * @throws IllegalArgumentException
  67.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  68.      * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_MD5, byte[])}
  69.      */
  70.     @Deprecated
  71.     public static Mac getHmacMd5(final byte[] key) {
  72.         return getInitializedMac(HmacAlgorithms.HMAC_MD5, key);
  73.     }

  74.     /**
  75.      * Returns an initialized {@code Mac} for the HmacSHA1 algorithm.
  76.      * <p>
  77.      * Every implementation of the Java platform is required to support this standard Mac algorithm.
  78.      * </p>
  79.      *
  80.      * @param key
  81.      *            The key for the keyed digest (must not be null)
  82.      * @return A Mac instance initialized with the given key.
  83.      * @see Mac#getInstance(String)
  84.      * @see Mac#init(Key)
  85.      * @throws IllegalArgumentException
  86.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  87.      * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_1, byte[])}
  88.      */
  89.     @Deprecated
  90.     public static Mac getHmacSha1(final byte[] key) {
  91.         return getInitializedMac(HmacAlgorithms.HMAC_SHA_1, key);
  92.     }

  93.     /**
  94.      * Returns an initialized {@code Mac} for the HmacSHA256 algorithm.
  95.      * <p>
  96.      * Every implementation of the Java platform is required to support this standard Mac algorithm.
  97.      * </p>
  98.      *
  99.      * @param key
  100.      *            The 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_SHA_256, byte[])}
  107.      */
  108.     @Deprecated
  109.     public static Mac getHmacSha256(final byte[] key) {
  110.         return getInitializedMac(HmacAlgorithms.HMAC_SHA_256, key);
  111.     }

  112.     /**
  113.      * Returns an initialized {@code Mac} for the HmacSHA384 algorithm.
  114.      * <p>
  115.      * Every implementation of the Java platform is <em>not</em> required to support this Mac algorithm.
  116.      * </p>
  117.      *
  118.      * @param key
  119.      *            The 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_384, byte[])}
  126.      */
  127.     @Deprecated
  128.     public static Mac getHmacSha384(final byte[] key) {
  129.         return getInitializedMac(HmacAlgorithms.HMAC_SHA_384, key);
  130.     }

  131.     /**
  132.      * Returns an initialized {@code Mac} for the HmacSHA512 algorithm.
  133.      * <p>
  134.      * Every implementation of the Java platform is <em>not</em> required to support this Mac algorithm.
  135.      * </p>
  136.      *
  137.      * @param key
  138.      *            The key for the keyed digest (must not be null)
  139.      * @return A Mac instance initialized with the given key.
  140.      * @see Mac#getInstance(String)
  141.      * @see Mac#init(Key)
  142.      * @throws IllegalArgumentException
  143.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  144.      * @deprecated (1.11) Use {@code getInitializedMac(HmacAlgorithms.HMAC_SHA_512, byte[])}
  145.      */
  146.     @Deprecated
  147.     public static Mac getHmacSha512(final byte[] key) {
  148.         return getInitializedMac(HmacAlgorithms.HMAC_SHA_512, key);
  149.     }

  150.     /**
  151.      * Returns an initialized {@code Mac} for the given {@code algorithm}.
  152.      *
  153.      * @param algorithm
  154.      *            the name of the algorithm requested. See
  155.      *            <a href= "https://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"
  156.      *            >Appendix A in the Java Cryptography Architecture Reference Guide</a> for information about standard
  157.      *            algorithm names.
  158.      * @param key
  159.      *            The 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.      */
  166.     public static Mac getInitializedMac(final HmacAlgorithms algorithm, final byte[] key) {
  167.         return getInitializedMac(algorithm.getName(), key);
  168.     }

  169.     /**
  170.      * Returns an initialized {@code Mac} for the given {@code algorithm}.
  171.      *
  172.      * @param algorithm
  173.      *            the name of the algorithm requested. See
  174.      *            <a href= "https://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"
  175.      *            >Appendix A in the Java Cryptography Architecture Reference Guide</a> for information about standard
  176.      *            algorithm names.
  177.      * @param key
  178.      *            The key for the keyed digest (must not be null)
  179.      * @return A Mac instance initialized with the given key.
  180.      * @see Mac#getInstance(String)
  181.      * @see Mac#init(Key)
  182.      * @throws IllegalArgumentException
  183.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  184.      */
  185.     public static Mac getInitializedMac(final String algorithm, final byte[] key) {
  186.         if (key == null) {
  187.             throw new IllegalArgumentException("Null key");
  188.         }
  189.         try {
  190.             final SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
  191.             final Mac mac = Mac.getInstance(algorithm);
  192.             mac.init(keySpec);
  193.             return mac;
  194.         } catch (final NoSuchAlgorithmException | InvalidKeyException e) {
  195.             throw new IllegalArgumentException(e);
  196.         }
  197.     }

  198.     /**
  199.      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
  200.      *
  201.      * @param key
  202.      *            The key for the keyed digest (must not be null)
  203.      * @param valueToDigest
  204.      *            The value (data) which should to digest (maybe empty or null)
  205.      * @return HmacMD5 MAC for the given key and value
  206.      * @throws IllegalArgumentException
  207.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  208.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmac(byte[])}
  209.      */
  210.     @Deprecated
  211.     public static byte[] hmacMd5(final byte[] key, final byte[] valueToDigest) {
  212.         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
  213.     }

  214.     /**
  215.      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
  216.      *
  217.      * @param key
  218.      *            The key for the keyed digest (must not be null)
  219.      * @param valueToDigest
  220.      *            The value (data) which should to digest
  221.      *            <p>
  222.      *            The InputStream must not be null and will not be closed
  223.      *            </p>
  224.      * @return HmacMD5 MAC for the given key and value
  225.      * @throws IOException
  226.      *             If an I/O error occurs.
  227.      * @throws IllegalArgumentException
  228.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  229.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmac(InputStream)}
  230.      */
  231.     @Deprecated
  232.     public static byte[] hmacMd5(final byte[] key, final InputStream valueToDigest) throws IOException {
  233.         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
  234.     }

  235.     /**
  236.      * Returns a HmacMD5 Message Authentication Code (MAC) for the given key and value.
  237.      *
  238.      * @param key
  239.      *            The key for the keyed digest (must not be null)
  240.      * @param valueToDigest
  241.      *            The value (data) which should to digest (maybe empty or null)
  242.      * @return HmacMD5 MAC for the given key and value
  243.      * @throws IllegalArgumentException
  244.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  245.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, String).hmac(String)}
  246.      */
  247.     @Deprecated
  248.     public static byte[] hmacMd5(final String key, final String valueToDigest) {
  249.         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmac(valueToDigest);
  250.     }

  251.     /**
  252.      * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
  253.      *
  254.      * @param key
  255.      *            The key for the keyed digest (must not be null)
  256.      * @param valueToDigest
  257.      *            The value (data) which should to digest (maybe empty or null)
  258.      * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase)
  259.      * @throws IllegalArgumentException
  260.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  261.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(byte[])}
  262.      */
  263.     @Deprecated
  264.     public static String hmacMd5Hex(final byte[] key, final byte[] valueToDigest) {
  265.         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
  266.     }

  267.     /**
  268.      * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
  269.      *
  270.      * @param key
  271.      *            The key for the keyed digest (must not be null)
  272.      * @param valueToDigest
  273.      *            The value (data) which should to digest
  274.      *            <p>
  275.      *            The InputStream must not be null and will not be closed
  276.      *            </p>
  277.      * @return HmacMD5 MAC for the given key and value as a hexadecimal string (lowercase)
  278.      * @throws IOException
  279.      *             If an I/O error occurs.
  280.      * @throws IllegalArgumentException
  281.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  282.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_MD5, byte[]).hmacHex(InputStream)}
  283.      */
  284.     @Deprecated
  285.     public static String hmacMd5Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
  286.         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
  287.     }

  288.     /**
  289.      * Returns a HmacMD5 Message Authentication Code (MAC) as a hexadecimal string (lowercase) for the given key and value.
  290.      *
  291.      * @param key
  292.      *            The 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 as a hexadecimal string (lowercase)
  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).hmacHex(String)}
  299.      */
  300.     @Deprecated
  301.     public static String hmacMd5Hex(final String key, final String valueToDigest) {
  302.         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
  303.     }

  304.     /**
  305.      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
  306.      *
  307.      * @param key
  308.      *            The key for the keyed digest (must not be null)
  309.      * @param valueToDigest
  310.      *            The value (data) which should to digest (maybe empty or null)
  311.      * @return HmacSHA1 MAC for the given key and value
  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_SHA_1, byte[]).hmac(byte[])}
  315.      */
  316.     @Deprecated
  317.     public static byte[] hmacSha1(final byte[] key, final byte[] valueToDigest) {
  318.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
  319.     }

  320.     /**
  321.      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
  322.      *
  323.      * @param key
  324.      *            The key for the keyed digest (must not be null)
  325.      * @param valueToDigest
  326.      *            The value (data) which should to digest
  327.      *            <p>
  328.      *            The InputStream must not be null and will not be closed
  329.      *            </p>
  330.      * @return HmacSHA1 MAC for the given key and value
  331.      * @throws IOException
  332.      *             If an I/O error occurs.
  333.      * @throws IllegalArgumentException
  334.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  335.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmac(InputStream)}
  336.      */
  337.     @Deprecated
  338.     public static byte[] hmacSha1(final byte[] key, final InputStream valueToDigest) throws IOException {
  339.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
  340.     }

  341.     /**
  342.      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
  343.      *
  344.      * @param key
  345.      *            The key for the keyed digest (must not be null)
  346.      * @param valueToDigest
  347.      *            The value (data) which should to digest (maybe empty or null)
  348.      * @return HmacSHA1 MAC for the given key and value
  349.      * @throws IllegalArgumentException
  350.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  351.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmac(String)}
  352.      */
  353.     @Deprecated
  354.     public static byte[] hmacSha1(final String key, final String valueToDigest) {
  355.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
  356.     }

  357.     // hmacSha1

  358.     /**
  359.      * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  360.      *
  361.      * @param key
  362.      *            The key for the keyed digest (must not be null)
  363.      * @param valueToDigest
  364.      *            The value (data) which should to digest (maybe empty or null)
  365.      * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase)
  366.      * @throws IllegalArgumentException
  367.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  368.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(byte[])}
  369.      */
  370.     @Deprecated
  371.     public static String hmacSha1Hex(final byte[] key, final byte[] valueToDigest) {
  372.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
  373.     }

  374.     /**
  375.      * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  376.      *
  377.      * @param key
  378.      *            The key for the keyed digest (must not be null)
  379.      * @param valueToDigest
  380.      *            The value (data) which should to digest
  381.      *            <p>
  382.      *            The InputStream must not be null and will not be closed
  383.      *            </p>
  384.      * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase)
  385.      * @throws IOException
  386.      *             If an I/O error occurs.
  387.      * @throws IllegalArgumentException
  388.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  389.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, byte[]).hmacHex(InputStream)}
  390.      */
  391.     @Deprecated
  392.     public static String hmacSha1Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
  393.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
  394.     }

  395.     /**
  396.      * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  397.      *
  398.      * @param key
  399.      *            The key for the keyed digest (must not be null)
  400.      * @param valueToDigest
  401.      *            The value (data) which should to digest (maybe empty or null)
  402.      * @return HmacSHA1 MAC for the given key and value as hexadecimal string (lowercase)
  403.      * @throws IllegalArgumentException
  404.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  405.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_1, String).hmacHex(String)}
  406.      */
  407.     @Deprecated
  408.     public static String hmacSha1Hex(final String key, final String valueToDigest) {
  409.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmacHex(valueToDigest);
  410.     }

  411.     /**
  412.      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
  413.      *
  414.      * @param key
  415.      *            The key for the keyed digest (must not be null)
  416.      * @param valueToDigest
  417.      *            The value (data) which should to digest (maybe empty or null)
  418.      * @return HmacSHA256 MAC for the given key and value
  419.      * @throws IllegalArgumentException
  420.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  421.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(byte[])}
  422.      */
  423.     @Deprecated
  424.     public static byte[] hmacSha256(final byte[] key, final byte[] valueToDigest) {
  425.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
  426.     }

  427.     /**
  428.      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
  429.      *
  430.      * @param key
  431.      *            The key for the keyed digest (must not be null)
  432.      * @param valueToDigest
  433.      *            The value (data) which should to digest
  434.      *            <p>
  435.      *            The InputStream must not be null and will not be closed
  436.      *            </p>
  437.      * @return HmacSHA256 MAC for the given key and value
  438.      * @throws IOException
  439.      *             If an I/O error occurs.
  440.      * @throws IllegalArgumentException
  441.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  442.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmac(InputStream)}
  443.      */
  444.     @Deprecated
  445.     public static byte[] hmacSha256(final byte[] key, final InputStream valueToDigest) throws IOException {
  446.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
  447.     }

  448.     /**
  449.      * Returns a HmacSHA256 Message Authentication Code (MAC) for the given key and value.
  450.      *
  451.      * @param key
  452.      *            The key for the keyed digest (must not be null)
  453.      * @param valueToDigest
  454.      *            The value (data) which should to digest (maybe empty or null)
  455.      * @return HmacSHA256 MAC for the given key and value
  456.      * @throws IllegalArgumentException
  457.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  458.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmac(String)}
  459.      */
  460.     @Deprecated
  461.     public static byte[] hmacSha256(final String key, final String valueToDigest) {
  462.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmac(valueToDigest);
  463.     }

  464.     /**
  465.      * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  466.      *
  467.      * @param key
  468.      *            The key for the keyed digest (must not be null)
  469.      * @param valueToDigest
  470.      *            The value (data) which should to digest (maybe empty or null)
  471.      * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase)
  472.      * @throws IllegalArgumentException
  473.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  474.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(byte[])}
  475.      */
  476.     @Deprecated
  477.     public static String hmacSha256Hex(final byte[] key, final byte[] valueToDigest) {
  478.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
  479.     }

  480.     /**
  481.      * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  482.      *
  483.      * @param key
  484.      *            The key for the keyed digest (must not be null)
  485.      * @param valueToDigest
  486.      *            The value (data) which should to digest
  487.      *            <p>
  488.      *            The InputStream must not be null and will not be closed
  489.      *            </p>
  490.      * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase)
  491.      * @throws IOException
  492.      *             If an I/O error occurs.
  493.      * @throws IllegalArgumentException
  494.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  495.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, byte[]).hmacHex(InputStream)}
  496.      */
  497.     @Deprecated
  498.     public static String hmacSha256Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
  499.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
  500.     }

  501.     /**
  502.      * Returns a HmacSHA256 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  503.      *
  504.      * @param key
  505.      *            The key for the keyed digest (must not be null)
  506.      * @param valueToDigest
  507.      *            The value (data) which should to digest (maybe empty or null)
  508.      * @return HmacSHA256 MAC for the given key and value as hexadecimal string (lowercase)
  509.      * @throws IllegalArgumentException
  510.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  511.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_256, String).hmacHex(String)}
  512.      */
  513.     @Deprecated
  514.     public static String hmacSha256Hex(final String key, final String valueToDigest) {
  515.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
  516.     }

  517.     /**
  518.      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
  519.      *
  520.      * @param key
  521.      *            The key for the keyed digest (must not be null)
  522.      * @param valueToDigest
  523.      *            The value (data) which should to digest (maybe empty or null)
  524.      * @return HmacSHA384 MAC for the given key and value
  525.      * @throws IllegalArgumentException
  526.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  527.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(byte[])}
  528.      */
  529.     @Deprecated
  530.     public static byte[] hmacSha384(final byte[] key, final byte[] valueToDigest) {
  531.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
  532.     }

  533.     /**
  534.      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
  535.      *
  536.      * @param key
  537.      *            The key for the keyed digest (must not be null)
  538.      * @param valueToDigest
  539.      *            The value (data) which should to digest
  540.      *            <p>
  541.      *            The InputStream must not be null and will not be closed
  542.      *            </p>
  543.      * @return HmacSHA384 MAC for the given key and value
  544.      * @throws IOException
  545.      *             If an I/O error occurs.
  546.      * @throws IllegalArgumentException
  547.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  548.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmac(InputStream)}
  549.      */
  550.     @Deprecated
  551.     public static byte[] hmacSha384(final byte[] key, final InputStream valueToDigest) throws IOException {
  552.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
  553.     }

  554.     /**
  555.      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
  556.      *
  557.      * @param key
  558.      *            The key for the keyed digest (must not be null)
  559.      * @param valueToDigest
  560.      *            The value (data) which should to digest (maybe empty or null)
  561.      * @return HmacSHA384 MAC for the given key and value
  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_384, String).hmac(String)}
  565.      */
  566.     @Deprecated
  567.     public static byte[] hmacSha384(final String key, final String valueToDigest) {
  568.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
  569.     }

  570.     // hmacSha384

  571.     /**
  572.      * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  573.      *
  574.      * @param key
  575.      *            The 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 HmacSHA384 MAC for the given key and value as hexadecimal 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_384, byte[]).hmacHex(byte[])}
  582.      */
  583.     @Deprecated
  584.     public static String hmacSha384Hex(final byte[] key, final byte[] valueToDigest) {
  585.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
  586.     }

  587.     /**
  588.      * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  589.      *
  590.      * @param key
  591.      *            The key for the keyed digest (must not be null)
  592.      * @param valueToDigest
  593.      *            The value (data) which should to digest
  594.      *            <p>
  595.      *            The InputStream must not be null and will not be closed
  596.      *            </p>
  597.      * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase)
  598.      * @throws IOException
  599.      *             If an I/O error occurs.
  600.      * @throws IllegalArgumentException
  601.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  602.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, byte[]).hmacHex(InputStream)}
  603.      */
  604.     @Deprecated
  605.     public static String hmacSha384Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
  606.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
  607.     }

  608.     /**
  609.      * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  610.      *
  611.      * @param key
  612.      *            The key for the keyed digest (must not be null)
  613.      * @param valueToDigest
  614.      *            The value (data) which should to digest (maybe empty or null)
  615.      * @return HmacSHA384 MAC for the given key and value as hexadecimal string (lowercase)
  616.      * @throws IllegalArgumentException
  617.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  618.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_384, String).hmacHex(String)}
  619.      */
  620.     @Deprecated
  621.     public static String hmacSha384Hex(final String key, final String valueToDigest) {
  622.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
  623.     }

  624.     /**
  625.      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
  626.      *
  627.      * @param key
  628.      *            The key for the keyed digest (must not be null)
  629.      * @param valueToDigest
  630.      *            The value (data) which should to digest (maybe empty or null)
  631.      * @return HmacSHA512 MAC for the given key and value
  632.      * @throws IllegalArgumentException
  633.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  634.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(byte[])}
  635.      */
  636.     @Deprecated
  637.     public static byte[] hmacSha512(final byte[] key, final byte[] valueToDigest) {
  638.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
  639.     }

  640.     /**
  641.      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
  642.      *
  643.      * @param key
  644.      *            The key for the keyed digest (must not be null)
  645.      * @param valueToDigest
  646.      *            The value (data) which should to digest
  647.      *            <p>
  648.      *            The InputStream must not be null and will not be closed
  649.      *            </p>
  650.      * @return HmacSHA512 MAC for the given key and value
  651.      * @throws IOException
  652.      *             If an I/O error occurs.
  653.      * @throws IllegalArgumentException
  654.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  655.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmac(InputStream)}
  656.      */
  657.     @Deprecated
  658.     public static byte[] hmacSha512(final byte[] key, final InputStream valueToDigest) throws IOException {
  659.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
  660.     }

  661.     /**
  662.      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
  663.      *
  664.      * @param key
  665.      *            The key for the keyed digest (must not be null)
  666.      * @param valueToDigest
  667.      *            The value (data) which should to digest (maybe empty or null)
  668.      * @return HmacSHA512 MAC for the given key and value
  669.      * @throws IllegalArgumentException
  670.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  671.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmac(String)}
  672.      */
  673.     @Deprecated
  674.     public static byte[] hmacSha512(final String key, final String valueToDigest) {
  675.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
  676.     }

  677.     // hmacSha512

  678.     /**
  679.      * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  680.      *
  681.      * @param key
  682.      *            The key for the keyed digest (must not be null)
  683.      * @param valueToDigest
  684.      *            The value (data) which should to digest (maybe empty or null)
  685.      * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase)
  686.      * @throws IllegalArgumentException
  687.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  688.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(byte[])}
  689.      */
  690.     @Deprecated
  691.     public static String hmacSha512Hex(final byte[] key, final byte[] valueToDigest) {
  692.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
  693.     }

  694.     /**
  695.      * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  696.      *
  697.      * @param key
  698.      *            The key for the keyed digest (must not be null)
  699.      * @param valueToDigest
  700.      *            The value (data) which should to digest
  701.      *            <p>
  702.      *            The InputStream must not be null and will not be closed
  703.      *            </p>
  704.      * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase)
  705.      * @throws IOException
  706.      *             If an I/O error occurs.
  707.      * @throws IllegalArgumentException
  708.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  709.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, byte[]).hmacHex(InputStream)}
  710.      */
  711.     @Deprecated
  712.     public static String hmacSha512Hex(final byte[] key, final InputStream valueToDigest) throws IOException {
  713.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
  714.     }

  715.     /**
  716.      * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
  717.      *
  718.      * @param key
  719.      *            The key for the keyed digest (must not be null)
  720.      * @param valueToDigest
  721.      *            The value (data) which should to digest (maybe empty or null)
  722.      * @return HmacSHA512 MAC for the given key and value as hexadecimal string (lowercase)
  723.      * @throws IllegalArgumentException
  724.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  725.      * @deprecated (1.11) Use {@code new HmacUtils(HmacAlgorithms.HMAC_SHA_512, String).hmacHex(String)}
  726.      */
  727.     @Deprecated
  728.     public static String hmacSha512Hex(final String key, final String valueToDigest) {
  729.         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
  730.     }

  731.     /**
  732.      * Returns whether this algorithm is available
  733.      *
  734.      * @param name the name to check
  735.      * @return whether this algorithm is available
  736.      * @since 1.11
  737.      */
  738.     public static boolean isAvailable(final HmacAlgorithms name) {
  739.         try {
  740.             Mac.getInstance(name.getName());
  741.             return true;
  742.         } catch (final NoSuchAlgorithmException e) {
  743.             return false;
  744.         }
  745.     }

  746.     /**
  747.      * Returns whether this algorithm is available
  748.      *
  749.      * @param name the name to check
  750.      * @return whether this algorithm is available
  751.      * @since 1.11
  752.      */
  753.     public static boolean isAvailable(final String name) {
  754.         try {
  755.             Mac.getInstance(name);
  756.             return true;
  757.         } catch (final NoSuchAlgorithmException e) {
  758.             return false;
  759.         }
  760.     }

  761.     /**
  762.      * Resets and then updates the given {@link Mac} with the value.
  763.      *
  764.      * @param mac
  765.      *            the initialized {@link Mac} to update
  766.      * @param valueToDigest
  767.      *            the value to update the {@link Mac} with (maybe null or empty)
  768.      * @return the updated {@link Mac}
  769.      * @throws IllegalStateException
  770.      *             if the Mac was not initialized
  771.      */
  772.     public static Mac updateHmac(final Mac mac, final byte[] valueToDigest) {
  773.         mac.reset();
  774.         mac.update(valueToDigest);
  775.         return mac;
  776.     }

  777.     /**
  778.      * Resets and then updates the given {@link Mac} with the value.
  779.      *
  780.      * @param mac
  781.      *            the initialized {@link Mac} to update
  782.      * @param valueToDigest
  783.      *            the value to update the {@link Mac} with
  784.      *            <p>
  785.      *            The InputStream must not be null and will not be closed
  786.      *            </p>
  787.      * @return the updated {@link Mac}
  788.      * @throws IOException
  789.      *             If an I/O error occurs.
  790.      * @throws IllegalStateException
  791.      *             If the Mac was not initialized
  792.      */
  793.     public static Mac updateHmac(final Mac mac, final InputStream valueToDigest) throws IOException {
  794.         mac.reset();
  795.         final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
  796.         int read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);

  797.         while (read > -1) {
  798.             mac.update(buffer, 0, read);
  799.             read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH);
  800.         }

  801.         return mac;
  802.     }

  803.     /**
  804.      * Resets and then updates the given {@link Mac} with the value.
  805.      *
  806.      * @param mac
  807.      *            the initialized {@link Mac} to update
  808.      * @param valueToDigest
  809.      *            the value to update the {@link Mac} with (maybe null or empty)
  810.      * @return the updated {@link Mac}
  811.      * @throws IllegalStateException
  812.      *             if the Mac was not initialized
  813.      */
  814.     public static Mac updateHmac(final Mac mac, final String valueToDigest) {
  815.         mac.reset();
  816.         mac.update(StringUtils.getBytesUtf8(valueToDigest));
  817.         return mac;
  818.     }

  819.     private final Mac mac;

  820.     /**
  821.      * Preserves binary compatibility only.
  822.      * As for previous versions does not provide useful behavior
  823.      * @deprecated since 1.11; only useful to preserve binary compatibility
  824.      */
  825.     @Deprecated
  826.     public HmacUtils() {
  827.         this(null);
  828.     }

  829.     /**
  830.      * Creates an instance using the provided algorithm type.
  831.      *
  832.      * @param algorithm to use.
  833.      * @param key the key to use
  834.      * @throws IllegalArgumentException
  835.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  836.      * @since 1.11
  837.      */
  838.     public HmacUtils(final HmacAlgorithms algorithm, final byte[] key) {
  839.         this(algorithm.getName(), key);
  840.     }

  841.     /**
  842.      * Creates an instance using the provided algorithm type.
  843.      *
  844.      * @param algorithm to use
  845.      * @param  key the key to use
  846.      * @throws IllegalArgumentException
  847.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  848.      * @since 1.11
  849.      */
  850.     public HmacUtils(final HmacAlgorithms algorithm, final String key) {
  851.         this(algorithm.getName(), StringUtils.getBytesUtf8(key));
  852.     }

  853.     private HmacUtils(final Mac mac) {
  854.         this.mac = mac;
  855.     }

  856.     /**
  857.      * Creates an instance using the provided algorithm type.
  858.      *
  859.      * @param algorithm to use
  860.      * @param  key the key to use
  861.      * @throws IllegalArgumentException
  862.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  863.      * @since 1.11
  864.      */
  865.     public HmacUtils(final String algorithm, final byte[] key) {
  866.         this(getInitializedMac(algorithm, key));
  867.     }

  868.     /**
  869.      * Creates an instance using the provided algorithm type.
  870.      *
  871.      * @param algorithm to use
  872.      * @param  key the key to use
  873.      * @throws IllegalArgumentException
  874.      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
  875.      * @since 1.11
  876.      */
  877.     public HmacUtils(final String algorithm, final String key) {
  878.         this(algorithm, StringUtils.getBytesUtf8(key));
  879.     }

  880.     /**
  881.      * Returns the digest for the input data.
  882.      *
  883.      * @param valueToDigest the input to use
  884.      * @return the digest as a byte[]
  885.      * @since 1.11
  886.      */
  887.     public byte[] hmac(final byte[] valueToDigest) {
  888.         return mac.doFinal(valueToDigest);
  889.     }

  890.     /**
  891.      * Returns the digest for the input data.
  892.      *
  893.      * @param valueToDigest the input to use
  894.      * @return the digest as a byte[]
  895.      * @since 1.11
  896.      */
  897.     public byte[] hmac(final ByteBuffer valueToDigest) {
  898.         mac.update(valueToDigest);
  899.         return mac.doFinal();
  900.     }

  901.     /**
  902.      * Returns the digest for the file.
  903.      *
  904.      * @param valueToDigest the file to use
  905.      * @return the digest
  906.      * @throws IOException
  907.      *             If an I/O error occurs.
  908.      * @since 1.11
  909.      */
  910.     public byte[] hmac(final File valueToDigest) throws IOException {
  911.         try (BufferedInputStream stream = new BufferedInputStream(new FileInputStream(valueToDigest))) {
  912.             return hmac(stream);
  913.         }
  914.     }

  915.     /**
  916.      * Returns the digest for the stream.
  917.      *
  918.      * @param valueToDigest
  919.      *            the data to use
  920.      *            <p>
  921.      *            The InputStream must not be null and will not be closed
  922.      *            </p>
  923.      * @return the digest
  924.      * @throws IOException
  925.      *             If an I/O error occurs.
  926.      * @since 1.11
  927.      */
  928.     public byte[] hmac(final InputStream valueToDigest) throws IOException {
  929.         final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
  930.         int read;

  931.         while ((read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH)) > -1) {
  932.             mac.update(buffer, 0, read);
  933.         }
  934.         return mac.doFinal();
  935.     }

  936.     /**
  937.      * Returns the digest for the input data.
  938.      *
  939.      * @param valueToDigest the input to use, treated as UTF-8
  940.      * @return the digest as a byte[]
  941.      * @since 1.11
  942.      */
  943.     public byte[] hmac(final String valueToDigest) {
  944.         return mac.doFinal(StringUtils.getBytesUtf8(valueToDigest));
  945.     }

  946.     /**
  947.      * Returns the digest for the input data.
  948.      *
  949.      * @param valueToDigest the input to use
  950.      * @return the digest as a hexadecimal String
  951.      * @since 1.11
  952.      */
  953.     public String hmacHex(final byte[] valueToDigest) {
  954.         return Hex.encodeHexString(hmac(valueToDigest));
  955.     }

  956.     /**
  957.      * Returns the digest for the input data.
  958.      *
  959.      * @param valueToDigest the input to use
  960.      * @return the digest as a hexadecimal String
  961.      * @since 1.11
  962.      */
  963.     public String hmacHex(final ByteBuffer valueToDigest) {
  964.         return Hex.encodeHexString(hmac(valueToDigest));
  965.     }

  966.     /**
  967.      * Returns the digest for the file.
  968.      *
  969.      * @param valueToDigest the file to use
  970.      * @return the digest as a hexadecimal String
  971.      * @throws IOException
  972.      *             If an I/O error occurs.
  973.      * @since 1.11
  974.      */
  975.     public String hmacHex(final File valueToDigest) throws IOException {
  976.         return Hex.encodeHexString(hmac(valueToDigest));
  977.     }

  978.     /**
  979.      * Returns the digest for the stream.
  980.      *
  981.      * @param valueToDigest
  982.      *            the data to use
  983.      *            <p>
  984.      *            The InputStream must not be null and will not be closed
  985.      *            </p>
  986.      * @return the digest as a hexadecimal String
  987.      * @throws IOException
  988.      *             If an I/O error occurs.
  989.      * @since 1.11
  990.      */
  991.     public String hmacHex(final InputStream valueToDigest) throws IOException {
  992.         return Hex.encodeHexString(hmac(valueToDigest));
  993.     }

  994.     /**
  995.      * Returns the digest for the input data.
  996.      *
  997.      * @param valueToDigest the input to use, treated as UTF-8
  998.      * @return the digest as a hexadecimal String
  999.      * @since 1.11
  1000.      */
  1001.     public String hmacHex(final String valueToDigest) {
  1002.         return Hex.encodeHexString(hmac(valueToDigest));
  1003.     }

  1004. }