javaphpbase64hashcodehmacsha1

php and java hmac_sha1 hashing are not the same


I'm trying to hash a message to a server side (which I can't change his code) written in php and encoded by HMAC_SHA1 algorithm. I'm writing the code in Java. the php code is as follows:

$utf8Str = mb_convert_encoding($strToSign, "UTF-8");
$hmac_sha1_str = base64_encode(hash_hmac("sha1", $utf8Str, KEY));
$signature = urlencode($hmac_sha1_str);

my java code is:

private static String HashStringSign(String toHash){
try {
    String afterUTF = new String(toHash.getBytes(), "UTF-8");
    String res = hmac_sha1(afterUTF, SecretAccessKey);
    String signature = new String(Base64.encode(res.getBytes()));
    String result = URLEncoder.encode(signature);
        return result;
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException(e);
    }
}

private static String hmac_sha1(String value, String key) {
    try {
        // Get an hmac_sha1 key from the raw key bytes
        byte[] keyBytes = key.getBytes();           
        SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");

        // Get an hmac_sha1 Mac instance and initialize with the signing key
        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(signingKey);

        // Compute the hmac on input data bytes
        byte[] rawHmac = mac.doFinal(value.getBytes());

        // Convert raw bytes to Hex
        byte[] hexBytes = new Hex().encode(rawHmac);
        return new String(hexBytes, "UTF-8");
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

I followed each of the hashing methods used in the php code and in the same order as you can see. maybe there's a function(s) in java that works different in php?

I'm using - com.sun.org.apache.xml.internal.security.utils.Base64 java.net.URLEncoder, javax.crypto and org.apache.commons.codec.binary

Thanks!


Solution

  • In your hash_hmac function you need to set the 4th parameter to true.

    PHP Code not responsible, Java only:

    So now you say that you can't change the PHP side, you can do the following to your Java code.

    In your last step of the Java code, you converted the raw byte array to hexademical. However, PHP generates a base64-encoded hexademical instead of just hexademical.

    So that the end of your Java step, simply base64 encode your hexademical and you will get the same values. https://stackoverflow.com/questions/9845767/base64-encoder-java#