1

This is the java code. I am trying to replicate the same functionality in javascript.

 public String populateHMAC(String app_id, String mobile, String token,
                            String deviceId) {

    String hmac = null;
    try {
        CryptLib cryptLib = new CryptLib();
        String message = app_id + "|" + mobile + "|" + deviceId;
        byte[] tokenBytes = Base64.decode(token, 2);//cryptLib.hexStringToByteArray(token);

        String temp=Base64.encodeToString(cryptLib.SHA256(message),2);

        byte[] tempArr=Base64.decode(temp,2);

        byte[] hmacBytes = cryptLib.encrypt(
                cryptLib.SHA256(message),
                tokenBytes);
        hmac = Base64.encodeToString(hmacBytes, Base64.DEFAULT);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return hmac;
}

These are the functions inside CryptLib

public byte[] SHA256(String paramString) throws Exception {
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(paramString.getBytes("UTF-8"));
    byte[] digest = md.digest();
    return digest;
}

And the encrypt function

public byte[] encrypt(byte[] data, byte[] key) throws Exception {
    SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
    byte[] iv = new byte[16];
    IvParameterSpec ivSpec = new IvParameterSpec(iv);
    Cipher acipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    byte[] arrayOfByte1;
    acipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
    arrayOfByte1 = acipher.doFinal(data);
    return arrayOfByte1;
}

This is the javascript code for the same functionality. I am using the crypto-js library.

var crypto = require('crypto-js');

populateHMAC( app_id,  mobile, token, deviceId){

    var rawStr = token;
    var wordArray = crypto.enc.Utf8.parse(rawStr);
    var base64 = crypto.enc.Base64.stringify(wordArray);

    var enctoken=btoa(token);


    var message= app_id + "|" + mobile + "|" + deviceId;

    var decodedString= atob(enctoken);

    message=encodeURIComponent(message);

    var hash= crypto.SHA256(message);//.toString(crypto.enc.Utf8);

    console.log("params",decodedString,hash.toString(crypto.enc.Hex));


    var iv = crypto.enc.Hex.parse('0000000000000000'); 
    var encryptedString = crypto.AES.encrypt(hash, decodedString, {
                iv:iv,
                mode: crypto.mode.CBC,
                padding: crypto.pad.Pkcs7
            });

    var encodedString= encryptedString.ciphertext.toString(crypto.enc.Base64);


     return encodedString;
}

The two outputs are different and I am unable to figure out why.

2
  • The code you've presented here is not HMAC. It has some similarities with CBC-MAC, but that's also not it. Don't call it HMAC. I'd rather throw away this code and implement proper HMAC. Both Java and CryptoJS have native support for actual HMAC. Commented Aug 23, 2016 at 19:54
  • Yes, It is not hmac. But that's the function that I have to replicate. It is already set in stone so I cannot discard it. Commented Aug 25, 2016 at 7:58

1 Answer 1

1

The issues:

  • I don't see that an equivalent of encodeURIComponent is used in the Java code. You can remove that line.

  • decodedString is a "binary" string which CryptoJS will treat as a password. You actually want to convert the token to a binary representation that CryptoJS understands:

    var decodedString = crypto.enc.Base64.parse(token);
    

    Remove the other encoding and decoding steps at the beginning of your code.

  • '0000000000000000' is too short if it is supposed to be a Hex-encoded IV. It must be twice as long to get 16 bytes (32 hexits).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.