почему хэш HMAC PHP ('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);
}
но я получаю разные результаты для одного и того же ввода
Update: эта функция работает. Наслаждаться.
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();
}
3 ответов
выходные данные функции php являются строчными шестнадцатеричными цифрами, когда четвертый параметр равен false. Однако второй версии 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 возвращает хэш, используя необработанные двоичные данные (3-й параметр TRUE). Кроме того, кодировка base64 в PHP соответствует URL-адресу и имени файла safe base64 encoder в Java https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html#url.
для тех, кто может столкнуться с небольшим изменением (не работает) в результате Java по сравнению с PHP, моя проблема заключалась в возврате хэша из HmacSHA256
как строка, в то время как вы должны вернуть ее и передать 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;
}