Why PHP hash_hmac ('sha256') gives an excellent result than java sha256_HMAC

in PHP I have the following function:

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

I am trying to create a function in Java that will give the same result for the same "data" and "secret" parameters.

I tried using 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 feature works. Enjoy it.

 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(); } 
+7
java php sha256
source share
3 answers

The output of the php function is lowercase hexadecimal digits when the fourth parameter is false. However, your second version of java produces uppercase hexadecimal digits. Either correct the data difference, or you can change the fourth hash_hmac parameter to true, and it will probably match your first version of Java.

+2
source share

If you are trying to map drupal_hmac_base64 output to 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 the original binary data (third parameter is TRUE). Furthermore, base64 encoding in PHP matches the URL and safe base64 encoder for names in Java https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html#url .

+1
source share

For someone who might encounter a small change (not working) as a result of Java compared to PHP, my problem was to return the hash from HmacSHA256 as a String, while you have to return it and pass Hex as byte[] , The following are the working methods for modeling 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; } 
0
source share

All Articles