String to UTF8 to SHA256 to BASE64 - javascript

In C# I have the following code:
public static string GetHashCode(string p)
{
var a = new SHA256Managed();
return Convert.ToBase64String(a.ComputeHash(new System.Text.UTF8Encoding().GetBytes(p)));
}
And I have to achieve the same thing in Javascript, I was trying the following but it gives different result:
btoa((CryptoJS.SHA256(this.toUTF8Array(this.settingsService.Password)).toString(CryptoJS.enc.Hex)));
What am I supposed to do, what is wrong?
Example output for string 'aaa' for:
C#:1f9e1d76685d765aa3a6ff85dced2f0a04f612536df52696684aaa67787e6cdd
Js:NGVhNWM1MDhhNjU2NmU3NjI0MDU0M2Y4ZmViMDZmZDQ1Nzc3N2JlMzk1NDljNDAxNjQzNmFmZGE2NWQyMzMwZQ==

I'm not that familiar with CryptoJS but I think you are outputting hex which is not the same as base64.
This generates the same result as C# see fiddle
var utf8arr = CryptoJS.enc.Utf8.parse("apassword");
var hash = CryptoJS.SHA256(utf8arr);
var base64 = CryptoJS.enc.Base64.stringify(hash);
console.log(base64);

Related

Encrypting With CryptoJS

I am trying to use the CryptoJS library to get the same value as I'm getting from an encryption tool, but I'm not able to get the same encrypted value.
Result using encryption tool:
Base64 Encoded Key: SisBCd6mVzPzZP7cpl/HvjqdkCpnujnJKUu8iosq/Yc=
Value to Encrypt: 55554444
Encrypted (ECB) Base64 Encoded Value: MLnK8JOyp+J4CoaqcWTAnW==
Here is my code where I'm trying to get that same result:
var data = '55554444'
var key = 'SisBCd6mVzPzZP7cpl/HvjqdkCpnujnJKUu8iosq/Yc='
// encrypt with key
var encrypted_ecb = CryptoJS.AES.encrypt(data, key, {mode: CryptoJS.mode.ECB});
console.log('encrypted_ecb: ', encrypted_ecb.toString())
// to base64
var rawStr = encrypted_ecb;
var wordArray = CryptoJS.enc.Utf8.parse(rawStr);
var base64_ecb = CryptoJS.enc.Base64.stringify(wordArray);
console.log('encrypted_base64_ecb: ', base64_ecb);
// Console Result:
// encrypted_ecb: U2FsdGVkX196PQg/s6RPQr3V9GEjf/WP7qRXxVh5GEU=
// encrypted_base64_ecb: VTJGc2RHVmtYMTk2UFFnL3M2UlBRcjNWOUdFamYvV1A3cVJYeFZoNUdFVT0=
As you can see I am getting the result I get is far different than the result I'm getting with the tool. Can anyone point me in the right direction?
Thank you!
You'll need to parse the key as well. Change the following line
var key = 'SisBCd6mVzPzZP7cpl/HvjqdkCpnujnJKUu8iosq/Yc='
to
var key = CryptoJS.enc.Base64.parse('SisBCd6mVzPzZP7cpl/HvjqdkCpnujnJKUu8iosq/Yc=');

crypto-js wrong des-ecb decoding

I need to decrypt base64 string using base64 key with ECB mode and Iso10126 padding using DES.
In theory it is simple:
const decryptedKeyDes = CryptoJS.DES.decrypt(
encryptedData, // QAKH7qnKxZTIta...
ResponseParser.secretKey, // MfKhm... length=32
{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Iso10126
}
);
I get sigBytes:162response and after converting it to base64 (because then I need to ungzip) I get
byteLength:243 which is wrong, it should be byteLength:395 (I am just compering it with my correct Java code).
I have no idea what is wrong here.
I also tried to do it using node.js's crypto but I also get wrong and different result. I can't find how to set padding in crypto and I can get only utf8, binary or ascii
function encodeDesECB(textToEncode, keyString) {
var key = new Buffer(
"some key with 32 length".substring(0, 8),
"utf8"
);
var cipher = crypto.createDecipheriv("des-ecb", key, null);
cipher.setAutoPadding(false);
var c = cipher.update(textToEncode, "base64", "utf8");
c += cipher.final("utf8");
return c;
}
The java code is:
import javax.crypto.Cipher
import static javax.crypto.Cipher.DECRYPT_MODE
//CIPHER_ALGORITHM_MODE_PADDING = 'DESede/ECB/ISO10126Padding'
Cipher decryptingCipher = Cipher.getInstance(CIPHER_ALGORITHM_MODE_PADDING)
decryptingCipher.init(DECRYPT_MODE, secretKeySpec)
decryptingCipher.doFinal(data)
where secretKeySpec is object with algorithm: DESede and key, which is bit[] equal to mine.
I have no idea what is wrong in my code.
Does CryptoJs works wrong, or maybe I forgot about something in my decoding.
Do you have any clues what can be wrong?
Thanks to #Topaco I finally solved it.
The key has to be WordArray: CryptoJS.enc.Base64.parse('some key with 32 length')
The message has to be base64 string: QAKH7qnKxZTIta...;
Then you need to parse the response like this: tripleDesResult.toString(CryptoJS.enc.Base64)
Thanks again!

Similar Encrypt code in javascript as in C#

I use some remote api, they use such C# code:
SHA256Managed sha256Managed = new SHA256Managed();
byte[] passwordSaltBytes = Encoding.Unicode.GetBytes("zda");
byte[] hash = sha256Managed.ComputeHash(passwordSaltBytes);
string result = Convert.ToBase64String(hash);
Console.WriteLine("result = " + result); // result = NUbWRkT8QfzmDt/2kWaikNOZUXIDt7KKRghv0rTGIp4=
I need to get the same result in my javascript frontend code. Does somebody can help with such problem?
The answer is:
var utf8arr = CryptoJS.enc.Utf16LE.parse("zda");
var hash = CryptoJS.SHA256(utf8arr);
var base64 = CryptoJS.enc.Base64.stringify(hash);
console.log(base64);
Not quite obvious, but Unicode in C# is using UTF-16LE enconding.
So you can use CryptoJS to achieve the same result:
var utf16 = CryptoJS.enc.Utf16LE.parse("zda");
var hash = CryptoJS.SHA256(utf16);
var base64 = CryptoJS.enc.Base64.stringify(hash);
console.log(base64);

How to convert Byte[] formated image to Base64string using JavaScript

I want to display an image from sql db to my web page,
I got the image in the format
{byte[6317]}
How to convert it into Base64string.
Try this
Byte[] bytes = File.ReadAllBytes("path");
String file = Convert.ToBase64String(bytes);
And correspondingly, read back to file:
Byte[] bytes = Convert.FromBase64String(b64Str);
File.WriteAllBytes(path, bytes);
Javascript Approach with Base64.js library
Since u specified that u want to convert it using JavaScript you can do it with the Base64 JavaScript library. It has the following methods:
toByteArray - Takes a base64 string and returns a byte array
And
fromByteArray - Takes a byte array and returns a base64 string
Here is an example how you could do it. First, return from ASP.NET MVC a response like this:
return Json(new { Img = imageBytes }, JsonRequestBehavior.AllowGet);
And then on the client you can use jQuery getJson() function to get the JSON response from the MVC ImageController:
$.getJSON("/Image",function(result){
$.each(result, function(i, field){
var byteArray = result.Img;
var base64 = base64js.fromByteArray(byteArray);
$("#mainimg").attr('src', 'data:image/jpeg;base64,' + base64);
});
});
You can download the base64.js library from here:
https://github.com/beatgammit/base64-js
C# Convert approach
If you don't like the base64 javascript approach you could convert the byte array on the server with C# using:
String base64string = Convert.ToBase64String(imageBytes);
return Json(new { Img = base64string }, JsonRequestBehavior.AllowGet);
This would return the Base64 string in the JSON Result. Then you can easily set your img source from jQuery as displayed in the Javascript Approach example.
Try This Code,
byte[] imgBytes = (byte[])yourbytedata;
string base64String = Convert.ToBase64String(imgBytes, 0, imgBytes.Length);
string htmlstr = "data:image/png;base64," + base64String;

how to get Hmac code with javascript

I can get a hmac sing using Python as following:
import hmac, base64, hashlib
def make_sign():
hash_data = "data"
secret = "this is secret"
sha512 = hashlib.sha512
hmac_obj = hmac.new(secret, hash_data, sha512)
str_hash = hmac_obj.digest()
sign = base64.b64encode(str_hash)
hex_hash = hmac_obj.hexdigest()
hex_sign = base64.b64encode(hex_hash)
print "correct_sign:",sign
print "hex_digest_sign:",hex_sign
make_sign()
output:
correct_sign: Lg4pXNCIpitNQt2DLU19qWb+FxdsYZlK4LLncfkTzSidrYoFJLNolUziRqh09B5HyRdCTEP7enZp6/Te34FK1g==
hex_digest_sign: MmUwZTI5NWNkMDg4YTYyYjRkNDJkZDgzMmQ0ZDdkYTk2NmZlMTcxNzZjNjE5OTRhZTBiMmU3NzFmOTEzY2QyODlkYWQ4YTA1MjRiMzY4OTU0Y2UyNDZhODc0ZjQxZTQ3YzkxNzQyNGM0M2ZiN2E3NjY5ZWJmNGRlZGY4MTRhZDY=
but with js, I can get hex_digest_sign, but I need to get correct_sign for web request.
function make_request() {
hash_data = "data"
secret = "this is secret"
hmac = hmac_512(hash_data, secret)
var sign = $.base64.encode(hmac),
console.log("js_sign="+sign);
}
function hmac_512(message, secret) {
var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA512, secret);
hmac.update(message);
var hash = hmac.finalize();
return hash;
}
js output:
js_sign="MmUwZTI5NWNkMDg4YTYyYjRkNDJkZDgzMmQ0ZDdkYTk2NmZlMTcxNzZjNjE5OTRhZTBiMmU3NzFmOTEzY2QyODlkYWQ4YTA1MjRiMzY4OTU0Y2UyNDZhODc0ZjQxZTQ3YzkxNzQyNGM0M2ZiN2E3NjY5ZWJmNGRlZGY4MTRhZDY="
the correct sign is correct_sign: Lg4pXNCIpitNQt2DLU19qWb+FxdsYZlK4LLncfkTzSidrYoFJLNolUziRqh09B5HyRdCTEP7enZp6/Te34FK1g==
how to get it in js?
I suspect that you are running into trouble with types and encoding. According to the CryptoJS source, the iterative hashing style that you are using returns a WordArray once you call finalize().
With that, once you go to print the results, you are printing the contents of the WordArray.
The purpose for itterative hashing is typically if you have a large input, you can break it into chunks to work on one piece at a time. Try the below edit I made that removes this as it does not look like you need to iterate.
function hmac_512(message, secret) {
var newHMAC = CryptoJS.HmacSHA256(message, secret);
return newHMAC;
}
The above will simply return the HMAC in string form which, once Base64 encoded, should match the result you see in Python.
Hope this helps!

Categories