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.
Related
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;
}
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);
}
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
well I need a Base64 decoding function. But it is not returning desired output when i am working with binary data. I know atob and atob functions but my problem is I am implementing it in workers and the user agent chrome. chrome not at implemented atob, btoa functions in workers, so suggest me a base64 functions that works with binary data. Now I am using the below function it is not working for binary data.
var Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
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;
},
// public method for decoding
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;
},
// private method for UTF-8 decoding
_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;
}
}
Thanks in advance!!
I did a quick search and found a decoder that claims to decode binary data, though I have not tried it:
https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js
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?