I need to modify this (working) code and replace CryptoJS
functions with native JS.
The variable b64encoded
has the correct value, but my attempt with native code (encodedIncorrect
) is not. Can you help feed btoa
the correct input?
Working, but 3rd party libs cannot be used on the platform I'm developing for:
const encrypted = CryptoJS.HmacSHA1("message", "secret");
// encrypted = "0caf649feee4953d87bf903ac1176c45e028df16" << Hexadecimal encoded string
const b64encoded = CryptoJS.enc.Base64.stringify(encrypted);
// b64encoded = "DK9kn+7klT2Hv5A6wRdsReAo3xY="
Not working, specifically the encoding of a binary string by btoa
:
const encrypted_vendor = VENDOR.hmacSHA1("message", "secret") // Vendor-provided HMAC-SHA1 func
// encrypted_vendor = "0caf649feee4953d87bf903ac1176c45e028df16"
// Split hex string into two-character byte representations for binary conversion
function splitHex(hexString) {
let chunks = [];
for (var i = 0, charsLength = hexString.length; i < charsLength; i += 2) {
chunks.push(hexString.substring(i, i + 2));
}
}
// Convert hex characters to binary value
function hexCharToBinary(value) {
return (parseInt(value, 16).toString(2)).padStart(8, '0');
}
binaryChunks = splitHex(encrypted)
var binaryStr = ""
binaryChunks.forEach(i => binaryStr += hexCharToBinary(i))
// binaryStr = "0000110010101111011001001001111111101110111001001001010100111101100001111011111110010000001110101100000100010111011011000100010111100000001010001101111100010110"
encodedIncorrect = btoa(binaryStr)
// encodedIncorrect = "MDAwMDExMDAxMDEwMTExMTAxMTAwMTAwMTAwMTExMTExMTEwMTExMDExMTAwMTAwMTAwMTAxMDEwMDExMTEwMTEwMDAwMTExMTAxMTExMTExMDAxMDAwMDAwMTExMDEwMTEwMDAwMDEwMDAxMDExMTAxMTAxMTAwMDEwMDAxMDExMTEwMDAwMDAwMTAxMDAwMTEwMTExMTEwMDAxMDExMA=="
I've also verified that the binary output is correct using this site (https://cryptii.com/pipes/binary-to-base64), which encodes it to the correct base64 when set to binary input.
You are encoding the string representation of the binary digits, not the actual data.
You need a binary string, which you can construct e.g. using String.fromCharCode:
const hexString = "0caf649feee4953d87bf903ac1176c45e028df16"
// split into two character groups (one byte each), see e.g.
// https://stackoverflow.com/questions/6259515/how-can-i-split-a-string-into-segments-of-n-characters
// using /.{1,2}/g may be preferrable for potential error handling
// but if there is always an even amount of characters, it doesn't matter.
let hexCharacterPairs = hexString.match(/../g);
// parse two hex characters as number
let bytes = hexCharacterPairs.map(e => parseInt(e, 16));
// generate symbols from the bytes
let binaryStringSymbols = bytes.map(e => String.fromCharCode(e));
// get a string from all the symbols
let binaryString = binaryStringSymbols.join("");
// use the binary string to get a base64 encode
let base64 = btoa(binaryString);
console.log(base64);
// or in one line
console.log(btoa("0caf649feee4953d87bf903ac1176c45e028df16".match(/../g).map(e => String.fromCharCode(parseInt(e, 16))).join("")));
Note, that the above snippet has no error handling, e.g. for odd numbers of characters in the input, invalid characters, etc.