Search code examples
javascriptbigintegercryptojs

Converting a 64 bit number string to word array using CryptoJS


I want to know if a string with integer data can be converted to a CryptoJS word array correctly? Example. Can I convert "175950736337895418" into a word array the same way I can create a word array out of 175950736337895418 (int value).

I have some code that converts integer values to word array

 // Converts integer to byte array
 function getInt64Bytes( x ){
    var bytes = [];
    for(var i = 7;i>=0;i--){
        bytes[i] = x & 0xff;
        x = x>>8;
    }
    return bytes;
}

//converts the byte array to hex string
function bytesToHexStr(bytes) {
    for (var hex = [], i = 0; i < bytes.length; i++) {
        hex.push((bytes[i] >>> 4).toString(16));
        hex.push((bytes[i] & 0xF).toString(16));
    }
    return hex.join("");
}

// Main function to convert integer values to word array
function intToWords(counter){
    var bytes = getInt64Bytes(counter);
    var hexstr = bytesToHexStr(bytes);
    var words = CryptoJS.enc.Hex.parse(hexstr);
    return words;
}

Even this code doesn't work correctly as very large integer numbers (exceeding javascript limit of numbers 2^53 - 1) get rounded off. Hence I wanted a solution that could take the integer value as string and convert it to a word array correctly.

PS. I need this word array to calculate the HMAC value using the following code

CryptoJS.HmacSHA512(intToWords(counter), CryptoJS.enc.Hex.parse(key))

Solution

  • What you want is to parse big numbers from strings. Since this is necessary for RSA, you can use Tom Wu's JSBN to get that functionality. Be sure to include jsbn.js and jsbn2.js. Then you can use it like this:

    function intToWords(num, lengthInBytes) {
        var bigInt = new BigInteger();
        bigInt.fromString(num, 10); // radix is 10
        var hexNum = bigInt.toString(16); // radix is 16
        
        if (lengthInBytes && lengthInBytes * 2 >= hexNum.length) {
            hexNum = Array(lengthInBytes * 2 - hexNum.length + 1).join("0") + hexNum;
        }
    
        return CryptoJS.enc.Hex.parse(hexNum);
    }
    
    var num = "175950736337895418";
    numWords = intToWords(num);
    
    document.querySelector("#hexInt").innerHTML = "hexNum: " + numWords.toString();
    document.querySelector("#hexIntShort").innerHTML = "hexNumShort: " + intToWords("15646513", 8).toString();
    
    var key = CryptoJS.enc.Hex.parse("11223344ff");
    
    document.querySelector("#result").innerHTML = "hexHMAC: " + 
            CryptoJS.HmacSHA512(numWords, key).toString();
    <script src="https://cdn.rawgit.com/jasondavies/jsbn/master/jsbn.js"></script>
    <script src="https://cdn.rawgit.com/jasondavies/jsbn/master/jsbn2.js"></script>
    <script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/hmac-sha512.js"></script>
    <div id="hexInt"></div>
    <div id="hexIntShort"></div>
    <div id="result"></div>

    If you need the result in a specific length, then you can pass the number of required bytes as the second argument.