MAC doFinal дает разное значение для одних и тех же данных

#java

Вопрос:

У меня возникла проблема со следующим кодом

 public static void main(String[] args) throws NoSuchAlgorithmException {  String key = "test";  SecretKeySpec secretKeySpec = new   SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA512");  Mac mac = Mac.getInstance("HmacSHA512");    try {  if (null != mac) {  mac.init(secretKeySpec);  }  } catch (InvalidKeyException e) {    }   IntStream.range(1, 12).parallel().forEach(d-gt;{  final byte[] bytes = "somestring".getBytes(StandardCharsets.UTF_8);  final byte[] doFinal= mac.doFinal(bytes);  String digest = Base64.getEncoder().encodeToString(doFinal);  LOGGER.info("digest -- {} ", digest);  }); }  

Даже строка та же самая, но дайджесты, созданные с помощью mac.doFinal, отличаются. Это всего лишь демонстрация проблемы. Я использовал тот же код в своем приложении spring reactive, где mac-это компонент, и дайджест генерируется каждый раз, когда пользователь делает запрос, который является параллельным запросом, где я также видел это странное поведение.

Комментарии:

1. Вы вызываете mac.doFinal параллельно в одном экземпляре. По-моему, это плохая идея. Вы получаете противоречивые результаты, если просто используете обычный for цикл и создаете MAC последовательно?

2. (Если вам нужно выполнять операции параллельно, создайте новый Mac экземпляр в цикле.)

3. Цикл последовательности прекрасен, но есть реальный сценарий, например, у меня есть компонент mac, и я сгенерировал дайджест заголовков с помощью mac.doFinal (). это параллельный запрос в приложении шлюза. Теперь есть базовое приложение, которое снова генерирует дайджест для одних и тех же данных и сравнивает оба дайджеста, так что на этот раз это создаст проблему.

4. Параллельные запросы должны быть в порядке: до тех пор, пока каждый из них использует новый Mac экземпляр. Итак, как я уже сказал, для вашего тестового кода переместите Mac создание в тело forEach лямбды. По сути, проблема заключается в том, что вы одновременно изменяете общее состояние — вы не можете этого сделать и ожидать, что результаты будут действительными.

5. Создание экземпляра Mac каждый раз в приложении шлюза-дорогостоящая задача. Я переместил экземпляр Mac внутрь, теперь он работает нормально, но я не уверен в реальной причине, по которой mac.doFinal не генерирует один и тот же дайджест для одних и тех же данных?