Перейти к основному содержимому

HMAC на Java

· 4 мин. чтения

1. Обзор

Давайте рассмотрим сценарий, в котором две стороны хотят общаться, и им нужен подход для проверки того, что получаемые ими сообщения не были подделаны. Код аутентификации сообщения на основе хэша (HMAC) — хорошее решение.

В этом руководстве мы рассмотрим, как работать с алгоритмом HMAC в Java.

2. Хэшированный код аутентификации сообщения (HMAC)

HMAC — это криптографический метод, гарантирующий целостность сообщения между двумя сторонами .

Алгоритм HMAC состоит из секретного ключа и хэш-функции . Секретный ключ — это уникальная часть информации или строка символов. Это известно как отправителю, так и получателю сообщения.

Хеш-функция — это алгоритм отображения, который преобразует одну последовательность в другую последовательность.

На рисунке ниже показан высокоуровневый алгоритм HMAC:

./4f4501f6aace428de0558afdbbe4dc9c.png

HMAC использует криптографические хэш-функции, такие как MD5 и SHA-* .

3. HMAC с использованием API JDK

Java предоставляет встроенный класс Mac для создания HMAC. После инициализации объекта Mac мы вызываем метод doFinal() для выполнения операции HMAC. Этот метод возвращает массив байтов, содержащий результат HMAC.

Давайте определим метод вычисления 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()));
}

Давайте напишем пример теста, чтобы проиллюстрировать расчет HMAC:

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

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

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

assertEquals(hmacSHA256Value, result);
}

В этом тесте мы используем алгоритм HmacSHA512 с простыми строковыми данными и ключами. Затем мы утверждаем, что результат HMAC равен ожидаемым данным.

4. Библиотека Apache Commons

Библиотека 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.

Давайте создадим метод для генерации 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 = "foreach";
String key = "123456";

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

assertEquals(hmacMD5Value, result);
}

В этом тесте мы используем алгоритм HmacMD5 .

5. Библиотека BouncyCastle

Точно так же мы можем использовать и библиотеку BouncyCastle . BouncyCastle — это набор криптографических API, которые мы можем использовать в Java.

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() . Наконец, мы вызовем метод 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 = "foreach";
String key = "123456";

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

assertEquals(hmacSHA512Value, result);
}

В этом тесте мы используем алгоритм HmacSHA512 .

6. Заключение

HMAC обеспечивает проверку целостности данных. В этой статье мы узнали, как генерировать HMAC для входных строковых данных с использованием алгоритма HMAC в Java. Кроме того, мы обсудили использование библиотек Apache Commons и BouncyCastle при расчете HMAC.

Как всегда, полный исходный код статьи доступен на GitHub .