JS Base 64 decode - java encode - javascript

I have a string S, which I decode (Base 64) in js and send to java server.
Server needs to encode (Base 64) input.
The problem is that original input string S which I have in js before manipulations differs from encoded in java.
The encoding is "windows-1252".
In java I use java.util.Base64.
Base64.getEncoder().encode(str.getBytes("windows-1252"))
Lengths of original and encoded strings are equal, and most of chars are equal too, but some differs.
Original string is
"7y4+R/oWOGRo6vaV7k6uvVase5ial/E9L51gYfyhXys="
decoded is
"ï.>Gú8dhêöîN®½V¬{ñ=/`aü¡_+"
and in java I have
"7y4+R/oWOGRo6vY/7k6uvVasez8/P/E9Lz9gYfyhXys="
Is there any way to get the original string in java?
In js I used
function decode64(input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
var base64test = /[^A-Za-z0-9\+\/\=]/g;
if (base64test.exec(input)) {
alert("There were invalid base64 characters in the input text.\n" +
"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
"Expect errors in decoding.");
}
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do {
enc1 = keyStr.indexOf(input.charAt(i++));
enc2 = keyStr.indexOf(input.charAt(i++));
enc3 = keyStr.indexOf(input.charAt(i++));
enc4 = keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return unescape(output);
}

Related

Base64 Decode doesn't work with accent charaters

I'm using the logic in http://www.webtoolkit.info/javascript_base64.html#.Wqn0dB2WbCI to decode a string encoded in base64. Decoding works fine for all alphanumeric characters except for accent characters like è. The unicode for è is 232.
Would be great if somebody can explain the problem.
The code I've used is as follows:
function decode(input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
return output;
}

base64 encoding of byte array in javascript

I'm trying to figure out how to do the reverse encode of a script that I'm using. I have the decode function. I now have to create the encode function, and I'm struggling a bit, where it details
"chr2 = (enc2 >> 2) | ((enc3 & 0x0F) << "
I'm not sure exactly what this means, or how to ensure that the encoded data is padded correctly.
I'm using the decodeAsArray function, to turn into a byte array and that works just fine. Now just trying to do vice-versa, the opposite way to encode the base64, so I'm hoping to create a encodeFromArray function, where I give a byte array as the input to the function.
Base64 = {
_keyStr: ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+=",
decode: function( input ) {
var output = "";
var hex = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
var base64test = /[^A-Za-z0-9\+\.\=]/g;
do {
enc1 = this._keyStr.indexOf(input.charAt(i++)) ;
enc2 = this._keyStr.indexOf(input.charAt(i++)) ;
enc3 = this._keyStr.indexOf(input.charAt(i++)) ;
enc4 = this._keyStr.indexOf(input.charAt(i++)) ;
chr1 = (enc1 | ((enc2 & 3) << 6));
chr2 = (enc2 >> 2) | ((enc3 & 0x0F) << 4);
chr3 = (enc3 >> 4) | (enc4 << 2);
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return (output);
},
decodeAsArray: function (b) {
var d = this.decode(b),
a = [],
c;
for (c = 0; c < d.length; c++) {
a[c] = d.charCodeAt(c)
}
return a
}
I think it would look something like the following:
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
}
However, I'm not sure how the enc2, enc3 and enc4 should be, based on the decode function, and then I'm also not sure how to do it from byte array
Treat the original encodings as these bits. The top 2 bits of each encoding are 00 because there are only 63 characters in base64 encoding, and that only requires 6 bits.
enc1 = 00abcdef
enc2 = 00ghijkl
enc3 = 00mnopqr
enc4 = 00stuvwx
The bit-shifting then produces:
chr1 = (enc1 | ((enc2 & 3) << 6)) = 00abcdef | 000000kl << 6 = klabcdef
chr2 = (enc2 >> 2) | ((enc3 & 0x0F) << 4) = 0000ghij | 0000opqr << 4 = opqrghij
chr3 = (enc3 >> 4) | (enc4 << 2) = 000000mn | stuvwx00 = stuvwxmn
So to reverse it, you need to do:
enc1 = chr1 & 0x3F;
enc2 = ((chr2 & 0x0F) << 2) | (chr1 >> 6);
enc3 = ((chr3 & 0x03 << 4) | (chr2 >> 4);
enc4 = chr3 >> 2;
So it looks like you had the correct formulas, but you were doing them backwards -- your enc1 is actually enc4.

Javascript - get contents of div, decode base64, replace the same div with decoded contents

Lets say I have a page with a div, which might or might not (no control over contents) have base64 encoded contents. I have a button, which when clicked will get the contents of the div, decode the base64 and then replace that same div with the decoded contents.
I know that innerHTML can get contents of whichever element.
I know that btoa() and atob() can decode base64, and there are enough functions on the web to do it for IE.
I however don't know how to combine the two, and afterwards replace the contents of that same div with the decoded result. What would be the best way to do above thing? Jquery is available, other frameworks are not.
You could use the jquery .html() method like this
<div class="encoded">SGVsbG8gV29ybGQ=</div>
and
$('.encoded').html(function(i,current){
return atob(current); //return the decoded string
});
Assuming that the div you want to target has a class encoded applied to it.. (that class is just an example for targeting the element)
Demo at http://jsfiddle.net/gaby/k5SSH/1//
You can use a function like this:
function encode64(input) {
input = escape(input);
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
keyStr.charAt(enc1) +
keyStr.charAt(enc2) +
keyStr.charAt(enc3) +
keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
}
function decode64(input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
var base64test = /[^A-Za-z0-9\+\/\=]/g;
if (base64test.exec(input)) {
alert("There were invalid base64 characters in the input text.\n" +
"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
"Expect errors in decoding.");
}
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do {
enc1 = keyStr.indexOf(input.charAt(i++));
enc2 = keyStr.indexOf(input.charAt(i++));
enc3 = keyStr.indexOf(input.charAt(i++));
enc4 = keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return unescape(output);
}
More Info: http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html

how to encode cookie data

I'm setting a cookie with some query string values for a page I've built, so that when you revisit the page you will have option set for you.
So if the URL is http://mysite.com/index.php?setting1=blue&orientation=horizontal&background=paper the cookie will store the setting1=blue, orientation=horizontal, and background=paper values to be read back on the next visit.
It seems like most people advise json encoding these values prior to storing in the cookie. However, I'm getting way bigger cookie sizes (like 4-5x bigger!) when json encoding vs. just saving these values in a standard query string format and parsing them later.
Any best practice for this situation?
Query string format is fine, if it's easy for you to parse them back.
Well, if you're using MooTools, simply use Hash.Cookie, it's nifty and will get you rid of your headaches by abstracting this stupid cookie storage stuff :)
If you want to convert a query string to an object take a look at
myQueryString.parseQueryString() // returns object of key value pairs
Requires mooTools More Strings: http://mootools.net/docs/more/Types/String.QueryString
However i like the idea of Base64 more! See below
Credit goes to Ryan Florence for this but this is what i use:
var cookieData = DATATOENCODE.toBase64() // base64 encodes the data
cookieData.decodeBase64() // to decode it
The magic:
/*
---
script: Base64.js
description: String methods for encoding and decoding Base64 data
license: MIT-style license.
authors: Ryan Florence (http://ryanflorence.com), webtoolkit.info
requires:
- core:1.2.4: [String]
provides: [String.toBase64, String.decodeBase64]
...
*/
(function(){
// Base64 string methods taken from http://www.webtoolkit.info/
var Base64 = {
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
};
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
};
return output;
},
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
};
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
};
};
output = Base64._utf8_decode(output);
return output;
},
// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
};
};
return utftext;
},
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
};
};
return string;
}
};
String.implement({
toBase64: function(){
return Base64.encode(this);
},
decodeBase64: function(){
return Base64.decode(this);
}
});
})();
I don't know if there is a best practice for this, but I would advise using the query string format since it's smaller.
Cookies are transferred with every page request. Less data transferred is almost always better.
If they're that much bigger, you're probably doing something wrong. setting1=blue can be represented as {"setting1":"blue"} - adding orientation=horizontal gives {"setting1":"blue","orientation":"horizontal"} - it definitely takes more space in the cookie but not that much.
Also, I'd personally recommend against using JSON. It's too easy for an attacker from a different website to set a cookie on your domain which could then get executed as JSON. The NVP "encoding" is more effective if you're only doing key/value storage.

Silverlight to Javascript interop UTF encoding/decoding

How do I get both alerts, one invoked from silverlight and the other invoked from javascript, to show the same data in the same way.
eg. ���� != ýÿýÿý
System.Windows.Browser.HtmlPage.Window.Alert( data );
alert(parameters);
Silverlight3 code, sending data to javascript function:
System.Windows.Browser.HtmlPage.Window.Alert( data );
// data contains binary data read from files
data = Convert.ToBase64String(Encoding.UTF8.GetBytes(data));
HtmlPage.Window.Eval("var data='"+data+"'makePOSTRequest('"+this.url+"',data);");
javascript function:
function makePOSTRequest(url,parameters)
{
...
parameters = UTF8.encode(decode64(parameters));
alert(parameters);
...
}
javascript library:
var UTF8 = {
// public method for url encoding
encode: function(string) {
string = string.replace(/\r\n/g, "\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// public method for url decoding
decode: function(utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while (i < utftext.length) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if ((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i + 1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i + 1);
c3 = utftext.charCodeAt(i + 2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}
var keyStr = "ABCDEFGHIJKLMNOP" +
"QRSTUVWXYZabcdef" +
"ghijklmnopqrstuv" +
"wxyz0123456789+/" +
"=";
function encode64(input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
keyStr.charAt(enc1) +
keyStr.charAt(enc2) +
keyStr.charAt(enc3) +
keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
}
function decode64(input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
var base64test = /[^A-Za-z0-9\+\/\=]/g;
if (base64test.exec(input)) {
alert("There were invalid base64 characters in the input text.\n" +
"Valid base64 characters are A-Z, a-z, 0-9, �+�, �/�, and �=�\n" +
"Expect errors in decoding.");
}
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do {
enc1 = keyStr.indexOf(input.charAt(i++));
enc2 = keyStr.indexOf(input.charAt(i++));
enc3 = keyStr.indexOf(input.charAt(i++));
enc4 = keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
}
Do you need to UTF-8 encode your characters, or do you just need a way to get these characters into the JavaScipt string? I would recommend using unicode escape sequences (see Unicode at at Mozilla Developer Center). For example, the copyright character is represented as "\u00A9". The nice thing about unicode escape sequences is they can exist in a source file that is encoded using iso-8859-1, but still allow for any unicode character.
See Converting Unicode strings to escaped ascii string for an example of how to do generate these escape sequences in C#.
You seem to be encoding the data as UTF-8 twice, you do it in silverlight:-
Encoding.UTF8.GetBytes(data)
and you do it again in Javascript
parameters = UTF8.encode(decode64(parameters));
are you sure this line shouldn't be:-
parameters = UTF8.decode(decode64(parameters));
?
Is there a reason you're not using WebClient or WebRequest inside Silverlight to do this posting?

Categories

Resources