How to convert a bit string to base64 in node.js? - javascript

I have a bit string that I want to convert to base64 but it doesn't look like there's a native function to do this and I couldn't find a node module either. ):
Input: 100110110101000110100011011001100010110100011011001100100110100011000001100000110000011000001100001001010100111110000011001111100101010011111010011100010110001001001001100000110100111010010100111110000111001000100000110001001000101100111110011001001001101011010001011001001101001010000011000100100100110000011010011
Output: base64 representation of that equivalent binary value
Maybe a better question is how to convert a bit string into a buffer? Not sure

As you guessed, the main thing is converting the string into something easier to convert to base64 and then converting that to base64.
In the code below, we do these conversion sequences:
bit string -> BigInt -> array of byte-sized ints -> binary string -> base64
base64 -> binary string -> array of byte-sized bit strings -> bit string
const encode = bitstr => {
const bytes = [];
// convert bit string to BigInt
let value = BigInt('0b' + bitstr);
// chop it up into bytes
while (value > 0n) {
bytes.unshift(Number(value & 0xffn));
value >>= 8n;
}
// convert to binary string and encode as base64
return btoa(String.fromCharCode.apply(null, bytes));
};
const decode = b64 => {
// decode base64 to binary string
const bstr = atob(b64);
// convert binary string to bit string
return new Array(bstr.length).fill(0).map(
(_,i) => bstr.charCodeAt(i).toString(2).padStart(8, i ? '0' : '')
).join('');
};
const bitstr = '100110110101000110100011011001100010110100011011001100100110100011000001100000110000011000001100001001010100111110000011001111100101010011111010011100010110001001001001100000110100111010010100111110000111001000100000110001001000101100111110011001001001101011010001011001001101001010000011000100100100110000011010011';
const encoded = encode(bitstr);
const decoded = decode(encoded);
console.log(bitstr);
console.log(encoded);
console.log(decoded);

Related

CryptoJS.enc.Base64.stringify analog on Kotlin (Android)

Code on JS
var base64 = CryptoJS.enc.Base64.stringify(requestContentString);
How do I rewrite it to Kotlin?
I write
val base64 = Base64.encodeToString(requestContentString.toByteArray(), Base64.DEFAULT)
But the answers are different
var base64 = CryptoJS.enc.Base64.stringify(**requestContentString**);
requestContentString is WordAray = CryptoJS.SHA256("String in here")
val base64 = Base64.encodeToString(requestContentString.toByteArray(), Base64.DEFAULT)
Now you have string hashed in SHA-256 and encoded on Base64
Same result in kotlin
First hash string to SHA-256
val bytes = MessageDigest
.getInstance("SHA-256")
.digest(input.toByteArray())
Encode on Base64
val encodedString1 = Base64.encodeToString(bytes,Base64.NO_WRAP)

How to pass a binary string to `btoa` to encode the raw value

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.

How to SHA-256 hash text in a chrome extension with SubtleCrypto

I am hashing a text field with Subtle Crypto and getting an [object ArrayBuffer].
The relevant code is here:
async function asyncCall() {
var enc = new TextEncoder(); // always utf-8
var enc2 = new TextDecoder(); // always utf-8
var digest3 = enc.encode(localStorage.getItem("Item 1"));
const digest2 = await crypto.subtle.digest("SHA-256", (digest3));
localStorage.setItem("Item Hashed", (digest2));
field2.value = localStorage.getItem("Item Hashed");
};
When I hash any text ("Item 1" is localStorage text that is defined with a text field) with this, I get [object ArrayBuffer] as the result. Why am I not getting something that looks like a SHA256 hash?
Convert ArrayBuffer to a Hex string:
const hashArray = Array.from(new Uint8Array(digest2)); // convert buffer to byte array
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string

Decompressing string (from gzcompress) returns wrong result when special chars are involved

I'm trying to write a front end application in js and I am getting my data (Iā¤U\nšŸ˜˜šŸ˜˜šŸ˜˜) from a webserver.
jsFiddle https://jsfiddle.net/czmovg26/1/
Webserver:
<?php
print($compressed = base64_encode(gzcompress('I\u2764U\n\uD83D\uDE18\uD83D\uDE18\uD83D\uDE18', 6)));
?>
Frontend:
var b64Data = "eJzzjCk1MjczCY3Jiyl1sTB2AZKuhha42ABGUQ2i"; // === Iā¤U\nšŸ˜˜šŸ˜˜šŸ˜˜
// Decode base64 (convert ascii to binary)
var strData = atob(b64Data);
// Convert binary string to character-number array
var charData = strData.split('').map(function (x) {
return x.charCodeAt(0);
});
// Turn number array into byte-array
var binData = new Uint8Array(charData);
// Pako magic
var data = pako.inflate(binData);
// Convert gunzipped byteArray back to ascii string:
var decoded = String.fromCharCode.apply(null, new Uint8Array(data));
var r = /\\u([\d\w]{4})/gi;
decoded = decoded.replace(r, function(match, grp) {
return String.fromCharCode(parseInt(grp, 16));
});
decoded = unescape(decoded);
Now, the string looks the same when you print it in the console, but
console.log(decoded == "Iā¤U\nšŸ˜˜šŸ˜˜šŸ˜˜");
resturns false, and things like
var val = decoded.replace(RegExp("\n","g"), "<br>");
do not work.
The decompression must be the problem, as it works fine with a normal string, but I don't understand, what's wrong with the decompression.
In JavaScript a string literal with \n in it denotes a new line, if you were to log such a string to the console you would see it split along multiple lines.
If you take a look at the log of the decoded string you'd notice its on a single line.
This means your original string did not have a new line in it.
From your php you can see that very clearly. In php the escape slash only escapes the single quote in a single quoted php string, so for \n to represent a newline it has to be within a double quoted string.
<?php
print($compressed = base64_encode(gzcompress("I\u2764U\n\uD83D\uDE18\uD83D\uDE18\uD83D\uDE18", 6)));

convert Ascii into Hex in Java Script for comparison

I have an Ascii value (something like "#") that I want to convert into an hex in JavaSkript that I can compare this value with some other hex-values.
Are there any casting possiblities?
Best regards and thanks,
Florian
Convert Ascii strings into base64 (hex)
var b64 = btoa("##%##!##$%");
Convert base64 to Ascii:
atob(b64);
Don't know what you want to compare, beside equality.
// Convert a (UTF-8 or ASCII) string to HEX:
function stringToHex(string) {
return '0x'+[...string].map(char => char.codePointAt(0).toString(16)).join('')
}
// Convert a HEX string into a number:
function hexToNumber(hex) {
return parseInt(hex, 16)
}

Categories

Resources