Obtaining same Base64 encoded output of encrypted string in Java and JavaScript - javascript

After getting byte array encryptedMessageInBytes from AES encryption function call cipher.doFinal in Java, I convert the byte array to base64 like this:
String encryptedMessageInBase64 = new String(Base64.getEncoder().encode(encryptedMessageInBytes));
In JavaScript, I simply do .toString() to the output I get from CryptoJS.AES.encrypt method and I get exact same base64 string. i.e.
var encryptedMessageInBase64 = CryptoJS.AES.encrypt("Message", "Secret Passphrase").toString();
It gives same base64 string as in Java code.
However, in one of the Java source code, they have done like this:
String encryptedMessageInBase64 = Base64.getUrlEncoder().encodeToString(encryptedMessageInBytes);
What shall I do in JavaScript to obtain same base64 string?

Here is answer:
However, in one of the Java source code, they have done like this:
String encryptedMessageInBase64 = Base64.getUrlEncoder().encodeToString(encryptedMessageInBytes);*
Here, basically they have done UrlEncoding instead of Base64 encoding. It is nothing but replacing + and / characters with - and _ characters. Url encoding is when we want to send encoded string over HTTP where it treats these two as special characters this is why we need to replace them with some other characters which are HTTP friendly.

Related

Encode in Java and Decode in Javascript

I want to pass a Base64 Image to the front end in a parameter.
I tried to send normal Base64 but it was giving me an error, probably because of the special characters in the Base64 Image.
So I tried in Java:
String base64Signature = Base64.getEncoder().encodeToString(image); // Encode to base64
return URLEncoder.encode(base64Signature, "utf-8"); // This class contains static methods for converting a String to the application/x-www-form-urlencoded MIMEformat
And in Javascript data.Signature has the image data. Neither
vm.Signature = data.Signature;
or
vm.Signature = decodeURIComponent(data.Signature);
worked. I copied the image data String in a online converter and it didn't display anything.
How should I do this?
The problem could be that Java's URLEncoder encodes spaces as + signs and JavaScript's decoder expects spaces as %20s. You can try replacing the + signs, for example:
decodeURIComponent(data.Signature.replace(/\+/g, '%20'));

Produce same result as CryptoJS.enc.Base64 using PHP

I have a javascript function that I'm trying to convert to PHP, It uses CryptoJS library, speciafically components/enc-base64-min.js and rollups/md5.js. They can be found here.
In it is this bit of code
// Let's say str = 'hello';
var md5 = CryptoJS.MD5(str);
md5 = md5.toString(CryptoJS.enc.Base64);
// md5 outputs "XUFAKrxLKna5cZ2REBfFkg=="
I assumed the str variable is hashed using md5 then encoded to Base64, so I tried this simple code
$md5 = md5($str);
$md5 = base64_encode($md5);
// md5 outputs "MmZjMGE0MzNiMjg4MDNlNWI5NzkwNzgyZTRkNzdmMjI="
Then I tried validating both the outputs, looks like the JS output isnt even a valid Base64 string.
To understand further I tried to look for toString() parameter from W3Schools, but it doesnt make sense to me, as per the reference the parameter is supposed to be an integer (2, 8 or 16), then why is CryptoJS.enc.Base64 used instead?
My goal here isn't to produce a valid base64 encoded string using JS but rather to produce the same output using PHP.
php's md5() with a single parameter returns the md5 hash as a hex string.
Instead you want the raw bytes to be encoded into Base64 so you have to pass the optional parameter $raw_output too to md5() (set to true)
$md5 = md5($str, true);
http://php.net/manual/it/function.md5.php

base64 encoding in javascript decoding in php

I am trying to encode a string in javascript and decode it in php.
I use this code to put the string in a inputbox and then send it via form PUT.
document.getElementById('signature').value= b64EncodeUnicode(ab2str(signature));
And this code to decode
$signature=base64_decode($signature);
Here there is a jsfiddle for the encoding page:
https://jsfiddle.net/okaea662/
The problem is that I always get a string 98% correct but with some different characters.
For example: (the first string is the string printed in the inputbox)
¦S÷ä½m0×C|u>£áWÅàUù»¥ïs7Dþ1Ji%ýÊ{\ö°(úýýÁñxçO9Ù¡ö}XÇIWçβÆü8ú²ðÑOA¤nì6S+̽ i¼?¼ºNËÒo·a©8»eO|PPþBE=HèÑqaX©$Ì磰©b2(Ðç.$nÈR,ä_OX¾xè¥3éÂòkå¾ N,sáW§ÝáV:ö~Å×à<4)íÇKo¡L¤<Í»äA(!xón#WÙÕGù¾g!)ùC)]Q(*}?­Ìp
¦S÷ ä½m0×C|u>£áWÅàUù»¥ïs7Dþ1Ji%ýÊ{\ö°(úýýÁñxçO9Ù¡ö}XÇIWçβÆü8ú²ðÑOA¤nì6S+̽ i¼?¼ºNËÒo·a©8»eO|PPþBE=HèÑ qaX©$Ì磰©b2(Ðç.$nÈR,ä_OX¾xè¥3éÂòkå¾ N ,sá W§ÝáV:ö~Å×à<4)íÇKo¡L¤<Í»äA(!xón#WÙÕGù¾g!)ùC)]Q(*}?­Ìp
Note that the 4th character is distinct and then there is one or two more somewhere.
The string corresponds to a digital signature so these characters make the signature to be invalid.
I have no idea what is happening here. Any idea? I use Chrome browser and utf-8 encoding in header and metas (Firefox seems to use a different encoding in the inputbox but I will look that problem later)
EDIT:
The encoding to base64 apparently is not the problem. The base64 encoded string is the same in the browser than in the server. If I base64-decode it in javascript I get the original string but if I decode it in PHP I get a slightly different string.
EDIT2:
I still don't know what the problem is but I have avoided it sending the data in a blob with ajax.
Try using this command to encode your string with js:
var signature = document.getElementById('signature');
var base64 = window.btoa(signature);
Now with php, you simply use: base64_decode($signature)
If that doesn't work (I haven't tested it) there may be something wrong with the btoa func. So checkout this link here:
https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
There is a function in there that should work (if the above does not)
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
b64EncodeUnicode(signature); // "4pyTIMOgIGxhIG1vZGU="

Two way hashing JSON String in JavaScript for use in URL

I would like to take a JSON string and encrypt/hash/encode it so that I can put it into a URL so that it would resemble something such as seen below:
var stringToEncode = JSON.stringify({foo: 'baz', bar: [1,2,3,4,5], baz: {fizzle: 'buzz'}});
'www.myrandomurl.com/someurl/123fas234asf1543rasfsafda'
I would then like to take that encrypted/hashed/encoded string, and decode it back to its original JSON string so that I can use it to bind to various elements on a single-page AngularJS application.
The contents of the JSON string are not sensitive so security or complex hashing is not required. The only condition is that It needs to be a "URL/URI 'safe'" string that is hashed for vanity purposes like seen above.
I am limited in knowledge of encrypting/encoding however I have thought about simply encoding the string to Base64 and decoding it again.
Is this the best approach? What is a better method if not?
Use encodeURIComponent() to encode it for the url
To decode use the decodeURIComponent() function
Base64 is not URL safe since it can contain non url characters like / + -. (See this question)
If you want your url to not be too similair to the original string you can first covert to base64 and then encode and reverse by decoding and covrrtibg back from base 64
// to url
encodeURIComponent(btoa(str))
// from url
atob(decodeURIComponent(uri))

How to encode 256bit AES key using base64?

I am using NodeJS to interact with Amazon Web Services (specifically s3). I am attempting to use Server side encryption with customer keys. Only AES256 is allowed as an encryption method. The API specifies that the keys be base64 encoded.
At the moment I am merely testing the AWS api, I am using throwaway test files, so security (and secure key generation) are not an issue at the moment.
My problem is as follows: Given that I am in posession of a 256bit hexadecimal string, how do I obtain a base64 encoded string of the integer that that represents?
My first instinct was to first parse the Hexadecimal string as an integer, and convert it to a string using toString(radix) specifying a radix of 64. However toString() accepts a maximum radix of 36. Is there another way of doing this?
And even if I do this, is that a base64 encoded string of 256bit encryption key? The API reference just says that it expects a key that is "appropriate for use with the algorithm specified". (I am using the putObject method).
To convert a hex string to a base64 string in node.js, you can very easily use a Buffer;
var key_in_hex = '11223344556677881122334455667788'
var buf = new Buffer(key_in_hex, 'hex')
var str = buf.toString('base64')
...which will set str to the base64 equivalent of the hex string passed in ('112233...')
You could also of course combine it to a one liner;
var key_in_hex = '11223344556677881122334455667788'
var str = new Buffer(key_in_hex, 'hex').toString('base64')

Categories