1

I am migrating from .net core to reactjs and need to calculate hash. I stuck in this code where results are not equal. Here is the code of .net, _normKey and inputBytes are byte arrays and result stored in hash is also byte array. How can i convert this into reactjs.

    _normkey = [150, 68, 231, 118, 4, 194, 153, 75, 25, 195, 123, 71, 133, 198, 103, 2, 169, 52, 8, 149, 68, 220, 132, 39, 183, 158, 132, 105, 77, 48, 18, 243, 211, 178, 144, 109, 73, 36, 254, 215, 175, 134, 92, 49, 5, 216, 170, 123, 75, 26, 232, 181, 129, 76, 22, 223, 167, 110, 52, 249, 189, 128, 66, 3];
inputBytes = [49, 46, 48, 53, 51, 46, 48, 46, 55, 52, 51, 48, 52, 50, 49, 54, 65, 45, 67, 51, 68, 70, 45, 52, 55, 48, 66, 45, 66, 68, 67, 48, 45, 67, 57, 57, 55, 48, 54, 67, 51, 48, 65, 65, 69, 49, 46, 48, 53, 73, 110, 116, 101, 103, 114, 97, 65, 80, 73, 48, 101, 112, 97, 108, 101, 110, 122, 117, 101, 108, 97, 50, 64, 105, 110, 116, 101, 103, 114, 97, 112, 97, 114, 107, 105, 110, 103, 46, 99, 111, 109, 49, 50, 51, 52, 53, 49, 48, 48, 48, 55, 49, 51, 54, 49, 51, 53, 46, 46]
        byte[] hash = new HMACSHA256(_normKey).ComputeHash(inputBytes);
        if (hash.Length >= 8)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = hash.Length - 8; i < hash.Length; i++)
            {
                sb.Append(hash[i].ToString("X2"));
            }
            strRes = sb.ToString();
        }

Here is the code of Reactjs

var hash = CryptoJS.HmacSHA256(_normKey.toString(), inputBytes.toString());
console.log(hash)

When I pass _normkey and inputBytes without toString, It throws error key.clamps is not a function

qaxim al
  • 61
  • 1
  • 7
  • *results are not equal* - so you have already js code? Then show it, including input and results, then it's easier to find out what's wrong. – jps Mar 03 '21 at 10:19
  • _normkey = [150, 68, 231, 118, 4, 194, 153, 75, 25, 195, 123, 71, 133, 198, 103, 2, 169, 52, 8, 149, 68, 220, 132, 39, 183, 158, 132, 105, 77, 48, 18, 243, 211, 178, 144, 109, 73, 36, 254, 215, 175, 134, 92, 49, 5, 216, 170, 123, 75, 26, 232, 181, 129, 76, 22, 223, 167, 110, 52, 249, 189, 128, 66, 3] – qaxim al Mar 03 '21 at 10:23
  • inputBytes = [49, 46, 48, 53, 51, 46, 48, 46, 55, 52, 51, 48, 52, 50, 49, 54, 65, 45, 67, 51, 68, 70, 45, 52, 55, 48, 66, 45, 66, 68, 67, 48, 45, 67, 57, 57, 55, 48, 54, 67, 51, 48, 65, 65, 69, 49, 46, 48, 53, 73, 110, 116, 101, 103, 114, 97, 65, 80, 73, 48, 101, 112, 97, 108, 101, 110, 122, 117, 101, 108, 97, 50, 64, 105, 110, 116, 101, 103, 114, 97, 112, 97, 114, 107, 105, 110, 103, 46, 99, 111, 109, 49, 50, 51, 52, 53, 49, 48, 48, 48, 55, 49, 51, 54, 49, 51, 53, 46, 46] – qaxim al Mar 03 '21 at 10:26
  • hash length is 32 in .net core – qaxim al Mar 03 '21 at 10:29
  • Check Post again. I've added react code – qaxim al Mar 03 '21 at 10:33
  • `CryptoJS.HmacSHA256()` does not process byte arrays but `WordArray`s. Byte arrays can be converted into _typed arrays_, which can be passed _directly_ to `WordArray.Create()`, [here](https://github.com/brix/crypto-js/blob/develop/test/lib-typedarrays-test.js). Alternatively, _explicit_ conversions can be done, [here](https://gist.github.com/artjomb/7ef1ee574a411ba0dd1933c1ef4690d1) or conversions into hex (or base64) encoded strings, which in turn can be converted into `WordArray`s using the appropriate CryptoJS [encoders](https://cryptojs.gitbook.io/docs/#encoders). – Topaco Mar 03 '21 at 16:41
  • Not getting the same result. here is my code var hash = CryptoJS.HmacSHA256(_normKey, CryptoJS.lib.WordArray.create(inputBytes)); var hashInBase64 = hash.toString(CryptoJS.enc.Base64 ); hashInBase64 = bytes(hashInBase64); – qaxim al Mar 03 '21 at 19:59
  • I am getting this result : (44) [84, 113, 88, 70, 67, 75, 90, 87, 98, 110, 89, 107, 66, 85, 80, 52, 47, 114, 66, 118, 49, 70, 100, 51, 101, 43, 79, 86, 83, 99, 81, 66, 90, 68, 97, 118, 50, 109, 88, 83, 77, 119, 52, 61] while i need (32) [212, 2, 50, 4, 7 , ..... ] – qaxim al Mar 03 '21 at 20:01
  • Why should this work? Where is the conversion to a typed array of `inputBytes`? The conversion of `_normKey` is completely missing. – Topaco Mar 03 '21 at 20:42
  • Here is the convertion of byte array byteArrayToWordArray(ba) { var wa = [], i; for (i = 0; i < ba.length; i++) { wa[(i / 4) | 0] |= ba[i] << (24 - 8 * i); } return CryptoJS.lib.WordArray.create(wa, ba.length); } – qaxim al Mar 03 '21 at 21:10
  • var key = this.byteArrayToWordArray(_normKey); var message = this.byteArrayToWordArray(inputBytes);var hash = CryptoJS.HmacSHA256(key, message); var hashedArr = this.wordArrayToByteArray(hash, 32) – qaxim al Mar 03 '21 at 21:19
  • Here is my code and i am using same functions that i called from this link https://gist.github.com/artjomb/7ef1ee574a411ba0dd1933c1ef4690d1 – qaxim al Mar 03 '21 at 21:19
  • Now i am getting same length but different values (32) [20, 18, 179, 79, 78, 134, 208, 233, 223, 139, 229, 117, 88, 83, 242, 61, 186, 164, 255, 179, 12, 117, 60, 122, 224, 177, 18, 93, 212, 68, 44, 62] – qaxim al Mar 03 '21 at 21:21
  • I' ve posted a possible implementation, please see my answer. – Topaco Mar 03 '21 at 21:28

1 Answers1

1

The output of the C# code is:

79E024C70ABA8B39

CryptoJS cannot process arrays directly, only WordArrays:

  • _normkey and inputBytes can be converted to typed arrays. A typed array can be used as an argument of WordArray.create() and thus converted into a WordArray.
  • HmacSHA256() returns a WordArray that can be converted to a hex string using the hex encoder of CryptoJS. This encoding corresponds to the encoding used in the C# code. If needed the hex string can be converted to an array, see e.g. here.

A possible implementation is:

var _normkey = [150, 68, 231, 118, 4, 194, 153, 75, 25, 195, 123, 71, 133, 198, 103, 2, 169, 52, 8, 149, 68, 220, 132, 39, 183, 158, 132, 105, 77, 48, 18, 243, 211, 178, 144, 109, 73, 36, 254, 215, 175, 134, 92, 49, 5, 216, 170, 123, 75, 26, 232, 181, 129, 76, 22, 223, 167, 110, 52, 249, 189, 128, 66, 3]
var inputBytes = [49, 46, 48, 53, 51, 46, 48, 46, 55, 52, 51, 48, 52, 50, 49, 54, 65, 45, 67, 51, 68, 70, 45, 52, 55, 48, 66, 45, 66, 68, 67, 48, 45, 67, 57, 57, 55, 48, 54, 67, 51, 48, 65, 65, 69, 49, 46, 48, 53, 73, 110, 116, 101, 103, 114, 97, 65, 80, 73, 48, 101, 112, 97, 108, 101, 110, 122, 117, 101, 108, 97, 50, 64, 105, 110, 116, 101, 103, 114, 97, 112, 97, 114, 107, 105, 110, 103, 46, 99, 111, 109, 49, 50, 51, 52, 53, 49, 48, 48, 48, 55, 49, 51, 54, 49, 51, 53, 46, 46]

var normKeyWA = CryptoJS.lib.WordArray.create(new Uint8Array(_normkey));          // Convert into WordArray via typed array
var inputBytesWA = CryptoJS.lib.WordArray.create(new Uint8Array(inputBytes));

var hash = CryptoJS.HmacSHA256(
      inputBytesWA,
      normKeyWA
);

var last8BytesWA = CryptoJS.lib.WordArray.create(hash.words.slice((32 - 8) / 4));
var last8BytesHex = last8BytesWA.toString(CryptoJS.enc.Hex).toUpperCase();        // Convert into hex encoded string using CryptoJS's Hex encoder
var last8BytesArray = hexToBytes(last8BytesHex);                                  // Convert into array

console.log(last8BytesHex);
console.log(last8BytesArray);

// from https://stackoverflow.com/a/34356351/9014097
function hexToBytes(hex) {
    for (var bytes = [], c = 0; c < hex.length; c += 2)
        bytes.push(parseInt(hex.substr(c, 2), 16));
    return bytes;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

Alternatively, the conversion between array and WordArray can be done explicitly, e.g. with the implementation here.

Topaco
  • 40,594
  • 4
  • 35
  • 62