1. 概要

2つのパーティが通信を希望し、受信したメッセージが改ざんされていないことを確認するためのアプローチが必要なシナリオを考えてみましょう。 ハッシュベースのメッセージ認証コード(HMAC)は優れたソリューションです。

このチュートリアルでは、JavaでHMACアルゴリズムを操作する方法を見ていきます。

2. ハッシュメッセージ認証コード(HMAC)

HMACは、2者間のメッセージの整合性を保証する暗号化方式です。

HMACアルゴリズムは、秘密鍵とハッシュ関数で構成されています。 秘密鍵は、一意の情報または文字列です。 これは、メッセージの送信者と受信者の両方に認識されています。

ハッシュ関数は、あるシーケンスを別のシーケンスに変換するマッピングアルゴリズムです。

次の図は、高レベルのHMACアルゴリズムを示しています。

HMACは、MD5SHA-*などの暗号化ハッシュ関数を使用します。

3. JDKAPIを使用したHMAC

Javaは、HMAC生成用の組み込みMacクラスを提供します。 Mac オブジェクトを初期化した後、 doFinal()メソッドを呼び出してHMAC操作を実行します。 このメソッドは、HMACの結果を含むバイト配列を返します。

MD5、SHA-1、SHA-224、SHA-256、SHA-384、SHA-512などのさまざまなハッシュアルゴリズムを使用してHMACを計算する方法を定義しましょう。

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()));
}

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);
}

このテストでは、HmacSHA512アルゴリズムを単純な文字列データとキーで使用しています。 次に、HMACの結果が期待されるデータに等しいと主張します。

4. Apache Commons Library

Apache Commonsライブラリは、HMAC計算用のユーティリティクラスも提供します。

4.1. Maven依存関係の追加

Apache Commonsユーティリティクラスを使用するには、commons-codecをpom.xmlに追加する必要があります。

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

4.2. HmacUtilsクラス

HMACの計算には、HmacUtilsクラスを使用できます。 HmacUtils オブジェクトを初期化した後、 hmacHex()メソッドを呼び出してHMAC操作を実行します。 このメソッドは、HMACの結果を含む16進文字列を返します。

HMACを生成するためのメソッドを作成しましょう。

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

テストの例を書いてみましょう。

@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);
}

このテストでは、HmacMD5アルゴリズムを使用しています。

5. BouncyCastleライブラリ

同様に、BouncyCastleライブラリも使用できます。 BouncyCastleは、Javaで使用できる暗号化APIのコレクションです。

5.1. Maven依存関係の追加

ライブラリの操作を開始する前に、bcpkix-jdk15to18依存関係をpom.xmlファイルに追加する必要があります。

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

5.2. Hmacクラス

まず、使用するハッシュアルゴリズムに基づいてHMacクラスをインスタンス化します。 次に、 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();
}

以下は、文字列データの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);
}

このテストでは、HmacSHA512アルゴリズムを使用しています。

6. 結論

HMACはデータ整合性チェックを提供します。この記事では、JavaでHMACアルゴリズムを使用して入力文字列データのHMACを生成する方法を学習しました。 さらに、HMAC計算でのApacheCommonsおよびBouncyCastleライブラリの使用法についても説明しました。

いつものように、記事の完全なソースコードは、GitHubから入手できます。