почему PHP hash_hmac ('sha256') дает отличный результат, чем java sha256_HMAC

в PHP у меня есть следующая функция:

base64_encode(hash_hmac('sha256', $data, $secret, false)); 

Я пытаюсь создать функцию на Java, которая даст тот же результат для тех же «данных» и «секретных» параметров.

Я попытался использовать эту функцию:

 public static String base64sha256(String data, String secret) { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); sha256_HMAC.init(secret_key); byte[] res = sha256_HMAC.doFinal(data.getBytes()); return Base64.encodeToString(res, Base64.NO_WRAP); } 

Но я получаю разные результаты для одного и того же ввода


Обновление: эта функция работает. Наслаждаться.

 public static String base64sha256(String data, String secret) { String hash = null; try { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"); sha256_HMAC.init(secret_key); byte[] res = sha256_HMAC.doFinal(data.getBytes("UTF-8")); hash = getHex(res); hash = Base64.encodeToString(hash.getBytes("UTF-8"), Base64.NO_WRAP); } catch (Exception e){} return hash; } static final String HEXES = "0123456789abcdef"; public static String getHex( byte [] raw ) { if ( raw == null ) { return null; } final StringBuilder hex = new StringBuilder( 2 * raw.length ); for ( final byte b : raw ) { hex.append(HEXES.charAt((b & 0xF0) >> 4)) .append(HEXES.charAt((b & 0x0F))); } return hex.toString(); } 

Вывод функции php – это строчные шестнадцатеричные цифры, когда четвертый параметр является ложным. Однако ваша вторая версия java производит шестнадцатеричные цифры в верхнем регистре. Либо исправьте разницу случаев, либо вы можете изменить четвертый параметр hash_hmac на true, и это, вероятно, будет соответствовать вашей первой версии Java.

Если вы пытаетесь сопоставить вывод drupal_hmac_base64 с Java 8, вы можете использовать следующий код:

 final String ALGORITHM = "HmacSHA256"; Mac mac = Mac.getInstance(ALGORITHM); SecretKeySpec secret = new SecretKeySpec(authorizationKey.getBytes(), ALGORITHM); mac.init(secret); byte[] digest = mac.doFinal(body.getBytes()); hash = Base64.getUrlEncoder().withoutPadding().encodeToString(digest); return signature.equals(hash); 

Обратите внимание, что drupal возвращает хеш с использованием исходных двоичных данных (третий параметр TRUE). Кроме того, кодировка base64 в PHP сопоставляет безопасный кодер base64 URL и имя файла в Java https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html#url .

Для кого-то, кто может столкнуться с небольшим изменением (не работает) в результате Java по сравнению с PHP, моя проблема заключалась в возврате хэша из HmacSHA256 качестве String, в то время как вы должны его вернуть и передать Hex в качестве byte[] . Ниже приведены рабочие методы для моделирования PHP hash_hmac()

 public String hashValue(String message) { byte[] hash = toHmacSHA256(message); String hashHexed = toHex(hash); return hashHexed; } private String toHex(byte[] value) { String hexed = String.format("%040x", new BigInteger(1, value)); return hexed; } private byte[] toHmacSHA256(String value) { byte[] hash = null; try { SecretKey secretKey = new SecretKeySpec(PRIVATE_KEY.getBytes("UTF-8"), "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(secretKey); hash = mac.doFinal(value.getBytes("UTF-8")); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return hash; }