in PHP I have the following function:
base64_encode(hash_hmac('sha256', $data, $secret, false));
I'm trying to create a function in Java that will give the same result for the same "data" and "secret" parameters.
I tried to use this function:
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);
}
But I get different results for the same input
Update: This function works. Enjoy.
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();
}
The output of the php function are lowercase hex digits when the fourth parameter is false. Your second java version however produces uppercase hex digits. Either correct the case difference or you could change the fourth parameter of hash_hmac to true and it will probably match with your first Java version.
If trying to match output of drupal_hmac_base64 with Java 8, you can use the following code:
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);
Note that drupal returns a hash using raw binary data (3rd parameter TRUE). Also, base64 encoding in PHP matches the URL and Filename safe base64 encoder in Java https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html#url.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With