«1. Обзор
Давайте рассмотрим сценарий, в котором две стороны хотят общаться, и им нужен подход для проверки того, что полученные ими сообщения не были подделаны. Код аутентификации сообщения на основе хэша (HMAC) — хорошее решение.
В этом руководстве мы рассмотрим, как работать с алгоритмом HMAC в Java.
2. Хэшированный код аутентификации сообщения (HMAC)
HMAC — это криптографический метод, гарантирующий целостность сообщения между двумя сторонами.
Алгоритм HMAC состоит из секретного ключа и хеш-функции. Секретный ключ — это уникальная часть информации или строка символов. Это известно как отправителю, так и получателю сообщения.
Хеш-функция — это алгоритм отображения, который преобразует одну последовательность в другую последовательность.
На рисунке ниже показан высокоуровневый алгоритм HMAC:
HMAC использует криптографические хэш-функции, такие как MD5 и SHA-*.
3. HMAC с использованием JDK API
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 = "baeldung";
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 = "baeldung";
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 на основе алгоритма хеширования, который мы хотим использовать. Затем мы обновим объект 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 = "baeldung";
String key = "123456";
String result = HMACUtil.hmacWithBouncyCastle(hmacSHA512Algorithm, data, key);
assertEquals(hmacSHA512Value, result);
}
В этом тесте мы используем алгоритм HmacSHA512.
6. Заключение
HMAC обеспечивает проверку целостности данных. В этой статье мы узнали, как генерировать HMAC для входных строковых данных с использованием алгоритма HMAC в Java. Кроме того, мы обсудили использование библиотек Apache Commons и BouncyCastle при расчете HMAC.
Как всегда, полный исходный код статьи доступен на GitHub.