HMAC in Java – Java中的HMAC

最后修改: 2021年 11月 19日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Let’s consider a scenario in which two parties want to communicate, and they need an approach to verify that the messages they receive haven’t been tampered with. Hash-based Message Authentication Code (HMAC) is a good solution.

让我们考虑这样一个场景:双方想要进行通信,他们需要一种方法来验证他们收到的消息没有被篡改。基于哈希的消息验证码(HMAC)是一个不错的解决方案。

In this tutorial, we look at how to work with the HMAC algorithm in Java.

在本教程中,我们看一下如何在Java中使用HMAC算法。

2. Hashed Message Authentication Code (HMAC)

2.加密信息验证码(HMAC)

HMAC is a cryptographic method that guarantees the integrity of the message between two parties.

HMAC是一种加密方法,保证了双方之间信息的完整性

HMAC algorithm consists of a secret key and a hash function. The secret key is a unique piece of information or a string of characters. It is known both by the sender and the receiver of the message.

HMAC算法由一个秘钥和一个哈希函数组成。秘密密钥是一个独特的信息或一串字符。它为信息的发送方和接收方所知。

The hash function is a mapping algorithm that converts one sequence to another sequence.

散列函数是一种映射算法,将一个序列转换为另一个序列。

The below figure shows the high-level HMAC algorithm:

下图显示了高层的HMAC算法。

hmac in java

HMAC uses cryptographic hash functions such as MD5 and SHA-*.

HMAC使用加密的哈希函数,例如MD5SHA-*

3. HMAC Using JDK APIs

3.使用JDK APIs的HMAC

Java provides a built-in Mac class for HMAC generating. After initializing the Mac object, we call the doFinal() method to perform the HMAC operation. This method returns a byte array containing the HMAC result.

Java提供了一个内置的Mac,用于生成HMAC。初始化Mac对象后,我们调用doFinal()方法来执行HMAC操作。该方法返回一个包含HMAC结果的字节数组。

Let’s define a method for calculating the HMAC with the various hashing algorithms, such as MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512:

让我们定义一种方法,用各种散列算法计算HMAC,如MD5、SHA-1、SHA-224、SHA-256、SHA-384、SHA-512。

public static String hmacWithJava(String algorithm, String data, String key)
  throws NoSuchAlgorithmException, InvalidKeyException {
    SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
    Mac mac = Mac.getInstance(algorithm);
    mac.init(secretKeySpec);
    return bytesToHex(mac.doFinal(data.getBytes()));
}

Let’s write an example test to illustrate HMAC calculation:

让我们写一个测试例子来说明HMAC的计算。

@Test
public void givenDataAndKeyAndAlgorithm_whenHmacWithJava_thenSuccess()
    throws NoSuchAlgorithmException, InvalidKeyException {

    String hmacSHA256Value = "5b50d80c7dc7ae8bb1b1433cc0b99ecd2ac8397a555c6f75cb8a619ae35a0c35";
    String hmacSHA256Algorithm = "HmacSHA256";
    String data = "baeldung";
    String key = "123456";

    String result = HMACUtil.hmacWithJava(hmacSHA256Algorithm, data, key);

    assertEquals(hmacSHA256Value, result);
}

In this test, we’re using the HmacSHA512 algorithm with simple string data and keys. Then, we assert that the HMAC result is equal to the expected data.

在这个测试中,我们使用HmacSHA512算法与简单的字符串数据和密钥。然后,我们断言HMAC的结果与预期的数据相等。

4. Apache Commons Library

4.阿帕奇共享图书馆

The Apache Commons library also provides a utility class for HMAC calculation.

Apache Commons库也提供了一个用于HMAC计算的实用类。

4.1. Adding the Maven Dependency

4.1.添加Maven依赖项

To use the Apache Commons utility class, we’ll need to add the commons-codec to our pom.xml:

要使用Apache Commons实用类,我们需要将commons-codec添加到我们的pom.xml。

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>

4.2. HmacUtils Class

4.2 HammacUtils类

For calculating an HMAC, we can use the HmacUtils class. After initializing the HmacUtils object, we call the hmacHex() method to perform the HMAC operation. This method returns a hexadecimal string containing the HMAC result.

为了计算HMAC,我们可以使用HmacUtils。在初始化HmacUtils对象后,我们调用hmacHex()方法来执行HMAC操作。该方法返回一个包含HMAC结果的十六进制字符串。

Let’s create a method for generating the HMAC:

让我们创建一个生成HMAC的方法。

public static String hmacWithApacheCommons(String algorithm, String data, String key) {
    String hmac = new HmacUtils(algorithm, key).hmacHex(data);
    return hmac;
}

Let’s write an example test:

让我们写一个测试的例子。

@Test
public void givenDataAndKeyAndAlgorithm_whenHmacWithApacheCommons_thenSuccess() {

    String hmacMD5Value = "621dc816b3bf670212e0c261dc9bcdb6";
    String hmacMD5Algorithm = "HmacMD5";
    String data = "baeldung";
    String key = "123456";

    String result = HMACUtil.hmacWithApacheCommons(hmacMD5Algorithm, data, key);

    assertEquals(hmacMD5Value, result);
}

In this test, we’re using the HmacMD5 algorithm.

在这个测试中,我们使用HmacMD5算法。

5. BouncyCastle Library

5.蹦蹦跳跳的城堡图书馆

Similarly, we can also use the BouncyCastle library. BouncyCastle is a collection of cryptographic APIs that we can use in Java.

同样地,我们也可以使用BouncyCastle。BouncyCastle是一个加密API的集合,我们可以在Java中使用。

5.1. Adding the Maven Dependency

5.1.添加Maven依赖项

Before we start working with the library, we need to add the bcpkix-jdk15to18 dependency to our pom.xml file:

在我们开始使用该库之前,我们需要将bcpkix-jdk15to18依赖性添加到我们的pom.xml文件中。

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15to18</artifactId>
    <version>1.69</version>
</dependency>

5.2. Hmac Class

5.2.Hmac

We’ll start by instantiating the HMac class based on the hashing algorithm we want to use. Then we’ll update the HMAC object with input data using the update() method. Finally, we’ll call the doFinal() method to generate an HMAC code:

我们将从根据我们想要使用的散列算法实例化类开始。然后,我们将使用update()方法用输入数据更新HMAC对象。最后,我们将调用doFinal()方法来生成一个HMAC代码。

public static String hmacWithBouncyCastle(String algorithm, String data, String key) {
    Digest digest = getHashDigest(algorithm);

    HMac hMac = new HMac(digest);
    hMac.init(new KeyParameter(key.getBytes()));

    byte[] hmacIn = data.getBytes();
    hMac.update(hmacIn, 0, hmacIn.length);
    byte[] hmacOut = new byte[hMac.getMacSize()];

    hMac.doFinal(hmacOut, 0);
    return bytesToHex(hmacOut);
}

private static Digest getHashDigest(String algorithm) {
    switch (algorithm) {
      case "HmacMD5":
        return new MD5Digest();
      case "HmacSHA256":
        return new SHA256Digest();
      case "HmacSHA384":
        return new SHA384Digest();
      case "HmacSHA512":
        return new SHA512Digest();
    }
    return new SHA256Digest();
}

Below is an example that produces an HMAC for a string data and then verifies it:

下面是一个例子,为一个字符串数据生成HMAC,然后进行验证。

@Test
public void givenDataAndKeyAndAlgorithm_whenHmacWithBouncyCastle_thenSuccess() {

    String hmacSHA512Value = "b313a21908df55c9e322e3c65a4b0b7561ab1594ca806b3affbc0d769a1" +
      "290c1922aa6622587bea3c0c4d871470a6d06f54dbd20dbda84250e2741eb01f08e33";
    String hmacSHA512Algorithm = "HmacSHA512";
    String data = "baeldung";
    String key = "123456";

    String result = HMACUtil.hmacWithBouncyCastle(hmacSHA512Algorithm, data, key);

    assertEquals(hmacSHA512Value, result);
}

In this test, we’re using the HmacSHA512 algorithm.

在这个测试中,我们使用HmacSHA512算法。

6. Conclusion

6.结语

The HMAC provides a data integrity check. In this article, we learned how to generate HMAC for input strings data using the HMAC algorithm in Java. Additionally, we discussed the usage of the Apache Commons and BouncyCastle libraries in HMAC calculation.

HMAC提供了一个数据完整性检查。在这篇文章中,我们学习了如何在Java中使用HMAC算法为输入的字符串数据生成HMAC。此外,我们还讨论了Apache Commons和BouncyCastle库在HMAC计算中的用法。

As always, the complete source code of the article is available over on GitHub.

一如既往,该文章的完整源代码可在GitHub上获取