Javascript window.atob -> HEX - different result than expected - javascript

I have a BMP image and I need to send it to a device via TCP/IP. We already have the C library in our company, which can handle this, but I need to do it in JavaScript. Unfortunately, I don't have access to the source code of the library, nor to the device system.
This is a Base64 string of a sample image (a black&white checkmark):
Qk2+AAAAAAAAAD4AAAAoAAAAIAAAACAAAAABAAEAAAAAAIAAAADEDgAAxA4AAAAAAAAAAAAAAAAAAP///wD//////+H////A////gH///wB///4AP//8AD//+AAf//AAD//gAA//yAAH/5wAB/+8EAP/fjAB/394Af+++AD/vPwAf8P+AH///gA///9AH///v5///7/P///fx///7+P//+/z///38f//+/n///38///+/f///v3///97////hw==
I use window.atob and I am encoding it into HEX. I use this JS function:
function toHex(str) {
var result = '';
for (var i = 0; i < str.length; i++) {
result += str.charCodeAt(i).toString(16);
}
return result;
}
var str = window.atob(base64img);
var result = toHex(str);
It gives me this result, which is almost expected result:
424dbe00000003e0002800020000200001010000080000c4e00c4e00000000000000ffffff0ffffffffffe1ffffffc0ffffff807fffff07ffffe03ffffc03ffff801ffff00fffe00fffc807ff9c07ffbc103ff7e301ff7f781ffbef80ffbcfc07fc3fe07ffffe03fffff401fffffbf9fffffbfcfffffdfc7ffffefe3ffffeff3fffff7f1fffffbf9fffffdfcfffffefdfffffefdffffff7bffffff87
The library sends the exact same image correctly (the device accepts the message). This is how it looks like (copied from log):
be00424dbe000000000000003e000000280000002000000020000000010001000000000080000000c40e0000c40e0000000000000000000000000000ffffff00ffffffffffe1ffffffc0ffffff807fffff007ffffe003ffffc003ffff8001ffff0000fffe0000fffc80007ff9c0007ffbc10101003ff7e3001ff7f7801ffbef800ffbcfc007fc3fe007ffffe003fffff401fffffbf9fffffbfcfffffdfc7ffffefe3ffffeff3fffff7f1fffffbf9fffffdfcfffffefdfffffefdffffff7bffffff87
So this is what I need to get from Base64 in my JavaScript. Is it even possible? Or am I missing something?
Documentation for the library says the image has to be 2B binary data (Little Endian). I don't understand it. Should I encode the image any other way?

One option would be encode each byte separately to ensure correct endianness.
img = "Qk2+AAAAAAAAAD4AAAAoAAAAIAAAACAAAAABAAEAAAAAAIAAAADEDgAAxA4AAAAAAAAAAAAAAAAAAP///wD//////+H////A////gH///wB///4AP//8AD//+AAf//AAD//gAA//yAAH/5wAB/+8EAP/fjAB/394Af+++AD/vPwAf8P+AH///gA///9AH///v5///7/P///fx///7+P//+/z///38f//+/n///38///+/f///v3///97////hw=="
str = atob(img)
buf = []
function hex(str, pos) {
return ('000' + (str.charCodeAt(pos) || 0).toString(16)).substr(-2);
}
for (var i = 0; i < str.length; i+= 4) {
buf.push(hex(str, i+2));
buf.push(hex(str, i+3));
buf.push(hex(str, i+0));
buf.push(hex(str, i+1));
}
console.log(buf.join(''))
This doesn't match your desired output exactly, are you sure it corresponds to the given base64 string?
On the other side, your initial output looks better, 424d are correct bytes to start a BMP file (BM signature), while be00 are not.

This is a Base64 string of a sample image (a black&white checkmark)...
It gives me this result, which is almost expected result:
424dbe00000003e0002800020000200001010000080000c4e00c4e00000000000000ffffff0ffffffffffe1ffffffc0ffffff807fffff07ffffe03ffffc03ffff801ffff00fffe00fffc807ff9c07ffbc103ff7e301ff7f781ffbef80ffbcfc07fc3fe07ffffe03fffff401fffffbf9fffffbfcfffffdfc7ffffefe3ffffeff3fffff7f1fffffbf9fffffdfcfffffefdfffffefdffffff7bffffff87
What do you mean by "almost expected result"?, those bytes make the image below (save as .bmp).
Your expected "a black&white checkmark" image :
PS:
The correct .bmp file has 190 bytes. Your library version (copied from logs) gives result of 194 bytes.
The library's version of bytes has a beginning 2-byte short for file size. That is BE 00 (= 190 when read as endian of 00 BE) followed by rest of Bitmap file bytes (190 total bytes). This makes total of 190 bytes + the 2 bytes of short. Then it adds these two mysterious 10 and 10 bytes starting at position 114. Grand total of 194 bytes.
To me... the library is corrupting the already fine image bytes, but you say the device accepts it?
Does it accept the "almost expected result" hex bytes too?

Related

How to show binary photo inside <img> tag

I am wondering if there is a way to use binary photo that i get from a server.
So for example I have this kind of url mybackend.com/get_image?id=1 and as a response I get a photo.
This is the response that I console.log:
�PNG
IHDR
ռ��IDATx�� ���
U��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“E>�|�(�Q��G��“�HL}/�MwIEND�B`�
This value that i logged is binary i guess.
When I set <img src="mybackend.com/get_image?id=1" /> it works because browser first makes GET network call and makes this binary show probably under the hood.
I found bunch of answers regarding this and it usually says that I need to convert this into base64 and than insert it into src attribute. But they don't bring me near to showing photo.
Thanks
const base64Image = btoa(binaryImage);
const imageTag = `<img src="data:image/png,${base64Image}" />`
btoa has a caveat - the binary must have a specific string representation. The MDN article explains how to work around this:
// convert a Unicode string to a string in which
// each 16-bit unit occupies only one byte
function toBinary(string) {
const codeUnits = new Uint16Array(string.length);
for (let i = 0; i < codeUnits.length; i++) {
codeUnits[i] = string.charCodeAt(i);
}
return String.fromCharCode(...new Uint8Array(codeUnits.buffer));
}
// a string that contains characters occupying > 1 byte
const myString = "☸☹☺☻☼☾☿";
const converted = toBinary(myString);
const encoded = btoa(converted);
console.log(encoded); // OCY5JjomOyY8Jj4mPyY=
Though it may be easier to simply use a library which can do this out of the box, such as js-base64
<script src="https://cdn.jsdelivr.net/npm/js-base64#3.6.0/base64.min.js"></script>
Base64.fromUint8Array(binaryImage);

Encrypt and decrypt by parts do not seem to work

Consider the code:
const CryptoJS = require("crypto-js");
var key = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");
var iv = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f");
// encrypt
var aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv });
var ciphertextPart1 = aesEncryptor.process("Message Part 1");
var ciphertextPart2 = aesEncryptor.process("Message Part 2");
var ciphertextPart3 = aesEncryptor.process("Message Part 3");
var ciphertextPart4 = aesEncryptor.finalize();
// decrypt
var aesDecryptor = CryptoJS.algo.AES.createDecryptor(key, { iv: iv });
var plaintextPart1 = aesDecryptor.process(ciphertextPart1);
var plaintextPart2 = aesDecryptor.process(ciphertextPart2);
var plaintextPart3 = aesDecryptor.process(ciphertextPart3);
var plaintextPart4 = aesDecryptor.process(ciphertextPart4);
var plaintextPart5 = aesDecryptor.finalize();
console.log(plaintextPart5.toString());
Source: https://cryptojs.gitbook.io/docs/#ciphers
Maybe I am wrong, but I expected the messages to be decrypted.
The output is actually:
61676520506172742033
I have no idea what that output means and where that comes from.
If I print out another part, the same issue:
console.log(plaintextPart4.toString());
Output:
7373616765205061727420324d657373
Discussion
One comment says that I am wrong on my assumption regarding how the method works, a nice answer could nicely correct me as well! I know the difference, from my studies, between one-way encryption and by parts: it makes no sense to me the way it is actually working, it seems a bug. My ideia is that you could keep adding message to be encrypted, as we can do with hashing, in the case of hashing (from the same abovementioned source), it seems to work, why not for encryption as well?
I honestly expected this example to work since it is from the official documentation, and they do not mention anything.
Comprehensive documentation is a rare beast.
it makes no sense to me the way it is actually working, it seems a bug
It works like this:
const CryptoJS = require("crypto-js");
const original_message = " ...0, ...1, ...2, ...3, ...4, ...5, ...6, ...7, ...8, ...9, ...The End!"
var key = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");
var iv = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f");
const aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv });
const aesDecryptor = CryptoJS.algo.AES.createDecryptor(key, { iv: iv });
const fragment_size = 25
const e_acc = []
for(let i = 0 ; i*fragment_size < original_message.length ; ++i ) {
const slice = original_message.slice(i*fragment_size, i*fragment_size + fragment_size)
console.log("slice to encrypt", slice)
e_acc.push(aesEncryptor.process(slice));
}
e_acc.push(aesEncryptor.finalize());
let message = ""
for(let i = 0 ; i !== e_acc.length ; ++i ) {
message += aesDecryptor.process(e_acc[i]).toString(CryptoJS.enc.Utf8)
console.log("intermidiate message", message)
}
message += aesDecryptor.finalize().toString(CryptoJS.enc.Utf8)
console.log("full message", message)
[...] it supposes to be a trick that you can add information by parts
[...]
My idea is that you could keep adding message to be encrypted
And you can, the only thing is - you can't decipher parts of messages that do not fill a block. You can only get as much as fits into a chain of complete blocks.
Consider the code
const sum1 = solver.process("1+22+3")
const sum2 = solver.process("03")
const sum3 = solver.finalize()
Here you can get the intermediate sum1 - sum of 1 and 22. But you can't add 3 right away, because, as you can see later on, it is not actually 3 but 303. Same thing with sum2 - solver do not know yet if the 303 should be added or maybe it would become 3031234.... So the only thing the solver can do is to remember the 3 and then the 303, but not use it. Until you call finalize.
aesEncryptor is like the solver but much more complicated.
Let's get back to the aesDecryptor and why all of plaintextPart* contain only the parts of the message... Why do you need "Progressive Ciphering" in the first place? Probably because you are sending fragments over the net? The key word is fragments - they purposely do not contain all the previous parts of the message as they could weight gigabytes!
in the case of hashing [...], it seems to work, why not for encryption as well?
Hashing is a quite different thing. You can not expect that AES has all the same properties as hashing, as you can not expect that hashing has all the same properties as, for example, summation.
The .process method returns any new chunks of ciphertext that were generated by processing the plaintext given as the argument to .process along with any plaintext that was left over from earlier encryptor activity.
In this case the cipher algorithm is AES. Specifically it's AES-128, because the key used to create the encryptor is 128 bits long. AES-128 consumes plaintext in 128-bit (16-byte) blocks and emits 128 bits (16 bytes) of ciphertext for each plaintext block. This block-based processing is what produces the results that you didn't understand.
What happens with your program is:
var ciphertextPart1 = aesEncryptor.process("Message Part 1");
The encryptor is given 14 bytes of input. That's not enough to allow it to generate a ciphertext block, so .process returns an empty ciphertext result which you store in ciphertextPart1. The encryptor stores the unprocessed 14 bytes internally.
var ciphertextPart2 = aesEncryptor.process("Message Part 2");
This gives the encryptor a further 14 bytes. It appends those to the 14 bytes left over from the previous call, so it now has a total of 28 unprocessed bytes. It processes as many of those bytes as it can. That is, it processes the first 16 of those bytes ("Message Part1Me") and returns the ciphertext block for those 16 bytes, which you store in cipherText2. The encryptor now contains 12 unprocessed bytes.
var ciphertextPart3 = aesEncryptor.process("Message Part 3");
This gives the encryptor another 14 bytes. It now has 26 unprocessed bytes. It processes the first 16 of those bytes ("ssage Part2Mess") and returns the ciphertext block for those 16 bytes, which you store in cipherText3. The encryptor now contains 10 unprocessed bytes.
var ciphertextPart4 = aesEncryptor.finalize();
This forces the encryptor to process any unprocessed bytes. It can only work on 16-byte blocks, so it adds 6 bytes of padding to the remaining 10 unprocessed plaintext bytes ("age Part 3"), encrypts that block and returns the ciphertext for that block. You store that ciphertext block as ciphertextPart4.
And now you decrypt the ciphertext blocks.
var plaintextPart1 = aesDecryptor.process(ciphertextPart1);
cipherTextPart1 was an empty block, so plaintextPart1 will be empty and obviously the decryptor will retain no unprocessed ciphertext.
var plaintextPart2 = aesDecryptor.process(ciphertextPart2);
cipherTextPart2 contained the encrypted version of the first 16 bytes of the plaintext, so plaintextPart2 will contain "Message Part 1Me". The ciphertext input was exactly 16 bytes long, therefore the decryptor contains no unprocessed ciphertext.
var plaintextPart3 = aesDecryptor.process(ciphertextPart3);
cipherTextPart3 contained the encrypted version of the next 16 bytes of the plaintext, so plaintextPart3 will contain "ssage Part 2Mess". Again the decryptor is holding no unprocessed ciphertext.
var plaintextPart4 = aesDecryptor.process(ciphertextPart4);
cipherTextPart4 contained the encrypted version of the final 10 bytes of the plaintext, so plaintextPart3 will contain "age Part 3". No unprocessed ciphertext remains in the decryptor.
var plaintextPart5 = aesDecryptor.finalize();
The is no unprocessed ciphertext remaining in the decryptor, so finalize has no work to do and plaintextPart5 will be empty.

Valid base64 string for a jpeg

Is this a valid base64 string of jpeg?
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD
That characters in question are the '/9j/' after the 'base64,'
I'm guessing it could be to do with compression as it's JPEG.
As when compared to a base64 string of a png, the pattern is different, i.e. the character pattern is different from above.
data:image/png;base64,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
The origin of my problem is that i'm base64 encoding an array of canvases into .jpeg's and .png's - the .png's output fine whereas the .jpeg's always output as black boxes.
I'm capturing the images using html2canvas (javascript), they are 'images' of html nodes, I have played around with transparency issues, like setting the background of the dom nodes to white.
All of the jpeg images I am encoding have this '/9j/' pattern, i'm generating them in a loop so it may well be a common property all the images have.
I can't seem to find a decent tool online to validate base64 strings either.
Let's check:
$ echo -n '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgID' | base64 --decode | file -
/dev/stdin: JPEG image data, JFIF standard 1.01
So it's recognized as a valid JPEG header (this doesn't necessarily mean that the entire JPEG data is valid, though, but at least it looks like a JPEG).
The difference between the JPEG data and the PNG data is because the file formats are different. Also, / is a valid character in Base64.
You can do a js check. Not sure how efficient it will be.
function checkImage( str ) {
var _img = document.createElement( 'img' );
_img.onerror = function() {
reportError(str);
}
_img.src = str;
}
function reportError(str) {
alert('Invalid image :' + str)
}
Hope it helps.
The file type can be identified by magic number. With a JPEG the magic number is “ff d8 ff” at offset 0. If you encode this to Base64, you'll always get “/9j/”
First we have to specify what is valid:
An totally legit image with no errors when gets rendered to image.
As long as it can show something visually, ignore the errors.(may have resolution or size issues but we don't care.)
In the first case, we can use onerror to bind events.The function checks if the base64 string can be converted to a <img> without any error. It will not only catch all the broken images but also the ones can be displayed but have errors.
let checkImage = (str) => {
let img = new Image();
img.src = str;
img.onerror = () => { //do something }
}
Or if we just want something can be rendered as image no matter what errors it gives us, we can ignore the errors and directly check if the size of the image is available.
let checkImage = (str) => {
let img = new Image();
img.src = str;
img.onload= () => {
if(img.width==0 || img.height==0){ //do something}
}
}

Is binary hashing possible with CryptoJS?

I want to create an HOTP client using javascript similar to SpeakEasy
The above library is intended for server side javascript usage and it uses NodeJS.
I want to do the same thing on front end javascript in a browser but I haven't been able to use CryptoJS to achieve this behavior.
var key = "abc";
var counter = "123";
// create an octet array from the counter
var octet_array = new Array(8);
var counter_temp = counter;
for (var i = 0; i < 8; i++) {
var i_from_right = 7 - i;
// mask 255 over number to get last 8
octet_array[i_from_right] = counter_temp & 255;
// shift 8 and get ready to loop over the next batch of 8
counter_temp = counter_temp >> 8;
}
// There is no such class called as Buffer on Browsers (its node js)
var counter_buffer = new Buffer(octet_array);
var hash = CryptoJS.HmacSHA1(key,counter_buffer);
document.write("hex value "+ hash);
document.write("hash value "+ CryptoJS.enc.Hex.stringify(hash));
I know this is possible on a native platform like java (android) or objective c (ios)
Here is the corresponding implementation HOTP in Objective C but I doubt if it's possible to do on a web based front end.
Also, I highly doubt if such a thing is secure in browser because javascript is viewable from any browser. Any inputs suggestions would be useful. I am doing this for a POC. I am curious if anyone has used Hotp on web based platform.
There is no such language that supports binary data strings in the code. You need to encode the binary data into some format such as Hex or Base64 and let CryptoJS decode it into it's own internal binary format which you then can pass to the various CryptoJS functions:
var wordArrayFromUtf = CryptoJS.enc.Utf8.parse("test");
var wordArrayFromHex = CryptoJS.enc.Hex.parse("74657374"); // "test"
var wordArrayFromB64 = CryptoJS.enc.Base64.parse("dGVzdA=="); // "test"
Other functions are:
wordArrayFromHex.toString(CryptoJS.enc.Utf8) // "test"
CryptoJS.enc.Utf8.stringify(wordArrayFromB64) // "test"
If you pass a string into a CrypoJS function (not these here), it will be assumed to be a Utf8-encoded string. If you don't want that, you need to decode it yourself.
The code at http://caligatio.github.io/jsSHA/ works fine for SHA-512.
Drop the .js files, look in their test/test.html at line 515. It might look like a string to you but it is binary hex.
So their input is binary which is unmistaken. Don't get hung up on the fact it is sitting in a big string.

Buffer length smaller than expected

I'm creating a Buffer from a long string of hex but getting some size mismatching (when I try to decrypt it). Sure enough when I run the following code:
var hexData = fs.readFileSync(fileName).toString().trim();
var bufferData = new Buffer(hexData, 'hex');
console.log(Buffer.byteLength(hexData, 'hex'));
console.log(bufferData.length);
my output is:
232548
30
Why is the whole string not being loaded into the Buffer?
EDIT: I noticed I was being silly and should be doing
var bufferData = fs.readFileSync(fileName, 'hex');
But the length of that is 930194!
Assuming you meant hexData and not data when you build bufferData, Buffer.byteLength seems to happily accept malformed hex, whereas the Buffer constructor will strip it out of the buffer. Consider:
> Buffer.byteLength('ff00junk', 'hex')
4
> var b = new Buffer('ff00junk', 'hex')
> b.length
2
> b
<Buffer ff 00>
Perhaps your file contains invalid hex?

Categories