Raúl Roa
Raúl Roa

Reputation: 12386

HMAC-SHA256 in Java produces different output than JavaScript

I've been trying to port some NodeJS code to Java in order to make HMAC signed requests to an API. I've been able to simplify the code to a point were encoding is clearly affecting the output.

Here's my code in JavaScript:

var APIKey = "secret";
var secretByteArray = CryptoJS.enc.Base64.parse(APIKey);
var hash = CryptoJS.HmacSHA256("Message", secretByteArray);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
//alert(hashInBase64);
document.write(hashInBase64);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/enc-base64.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/hmac-sha256.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"></script>

Here's the Java Code:

try {
        String secret = "secret";
        String message = "Message";

        byte[] secretByteArray = Base64.getEncoder().encode(secret.getBytes());

        //byte[] secretByteArray = Base64.encodeBase64(secret.getBytes("utf-8"), true);

        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secretByteArray, "HmacSHA256");
        sha256_HMAC.init(secret_key);

        String hash = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(message.getBytes()));
        System.out.println(hash);
    }
    catch (Exception e){
        System.out.println("Error");
    }

If I don't encode to base64 the "secret" I get the same output, but I'd like to get the same result with encoded strings. I suspect the encoded byte arrays have padding or sign differences.

Upvotes: 4

Views: 7162

Answers (1)

SLaks
SLaks

Reputation: 887195

Your Java code uses Base64.getEncoder().encode to convert to Base64.

Your JavaScript code uses CryptoJS.enc.Base64.parse to convert from Base64.

You need to make those match.

Upvotes: 9

Related Questions