Conversion from buffer to string gives different results in c# and Nodejs - javascript

I'm trying to convert this function from C# to node but I'm getting different results when I try to convert a buffer to a string.
string str = "34924979";
System.Security.Cryptography.SHA512 sha = new System.Security.Cryptography.SHA512Managed();
byte[] ba = System.Text.Encoding.ASCII.GetBytes(str);
byte[] data= sha.ComputeHash(ba);
Console.WriteLine(System.Text.Encoding.ASCII.GetString(data));
>> `?????gV)????∟?Z?s??v$We-??N?"?w????0??\i♠G???
that's what i'm trying to do.
const crypto = require('crypto')
const str = '34924979';
const sha = crypto.createHash('sha512').update(str).digest('utf8');
const hash = sha.toString('utf-8').replace(/\uFFFD/g, '?');
console.log(hash);
>> `????gV)????∟?Z?v$We-??N?"?w????0?\i♠Gߕ?

You're using different encodings in C# and JS.
Try changing the JS code to the following:
const sha = crypto.createHash('sha512').update(str).digest('ascii');
const hash = sha.toString('ascii');

Related

try to generating signature using HMACSHA512 in c#

signature in c# using HMACSHA512 not equivalent to java and JavaScript.
after tracing my c# code i found the key is not used during generating signature.
using System.Security.Cryptography;
using System.Text;
string privateKey = "OPAYPRV16388855997950.6319778282304234";
string message = "{\r\n \"country\": \"EG\",\r\n \"reference\": \"9cf357a79ffc4cb5a57cd0489a1a4bfa\"\r\n}";
byte[] messagebyte = Encoding.Default.GetBytes(message);
byte[] pkey = Encoding.Default.GetBytes(privateKey);
HMACSHA512 hMACSHA512 = new HMACSHA512(pkey);
//hMACSHA512.Key = pkey; //other way and not give right signature
//hmacsha512.Initialize();
var hmac = hMACSHA512.ComputeHash(messagebyte);
var hmacres = BitConverter.ToString(hmac).Replace("-", "");
Console.WriteLine(hmacres);
// signature c# =FC96AABB47DE439A78CB98943BA3E9F9C25B24264E1431CC4180348F5B48C869F9003E3B67B8E387D25A7189093ACDD90205A103A489856379971EBE07E295E5
// signature in java and JavaScript (the same and the right signature)=
20c8b06951a7907b48db0ccb0b1fb514e8addb2b7c72786cc21316576d57e57560188cac837ffe232a9b24e65e73c6c05e6a5dddff3cc03e26521c92e74e064d
HMACSHA512 deal with \r\n and spaces as characters, when remove /r/n and space I got the right signature
message= message.Replace(System.Environment.NewLine, string.Empty).Replace(" ", "");
byte[] messagebyte = Encoding.Default.GetBytes(message);
byte[] pkey = Encoding.Default.GetBytes(privateKey);
HMACSHA512 hMACSHA512 = new HMACSHA512(pkey);
var hmac = hMACSHA512.ComputeHash(messagebyte);
var hmacres = BitConverter.ToString(hmac).Replace("-", "");

Confused on how to implement HMACSHA1 in C# .NET coming from javascript

I am using the crypto-js library to implement the HMACSHA1 for my javascript code
the code looks like this
const hash1 = require("crypto-js");
let signature = "application_id=3610&auth_key=aDRceQyTXSYEdJU&nonce=6304033672&timestamp=1623098533&user[login]=john#mail.com&user[password]=123456789"
let key = "dBV2PdhYMnruSMb"
let hash = hash1.HmacSHA1(signature, key).toString()
console.log(hash)
//which prints
467280c4cb82fc97bd04c51d8a846446ad6e82e1
this obviously is pretty easy in javascript. But then I tried using the same exact string and key in c# and it prints out a completely different string. I am lost and don't know how to solve this issue.
Here is my attempt to implement this in C#
string signSession = "application_id=3610&auth_key=aDRceQyTXSYEdJU&nonce=6304033672&timestamp=1623098533&user[login]=john#mail.com&user[password]=123456789"
string key = "dBV2PdhYMnruSMb="
//convert the session signature string to a byte array
byte[] signature = Encoding.UTF8.GetBytes(signSession.ToString());
var apiKey = Convert.FromBase64String(key);
//Generate a HMACSHA1 signature
using(HMACSHA1 hmac = new HMACSHA1(apiKey))
{
byte[] signatureBytes = hmac.ComputeHash(signature);
string base64Signature = Convert.ToBase64String(signatureBytes);
Console.WriteLine(base64Signature);
session.Signature = base64Signature;
}
//And this prints
sztTnSTv2xvuA7pPXxk2cKMP0Eo=
//which is wrong. It should be the same as the javascript result
Im not sure what im doing wrong here and is my C# implementation right?
Your key is different. While crypto-js expects a string, C# expects a byte array. You shouldn't use FromBase64String() but Encoding.UTF8.GetBytes(). As #jps mentioned in the comment
Of course it's different, your JS implementation has a hex encoded
output but in your C# implementation you're base64 encoding the
result.
you should convert the byte-array to a hex-string like so
string signSession = "application_id=3610&auth_key=aDRceQyTXSYEdJU&nonce=6304033672&timestamp=1623098533&user[login]=john#mail.com&user[password]=123456789";
string key = "dBV2PdhYMnruSMb";
//convert the session signature string to a byte array
byte[] signature = Encoding.UTF8.GetBytes(signSession);
var apiKey = Encoding.UTF8.GetBytes(key);
//Generate a HMACSHA1 signature
using (HMACSHA1 hmac = new HMACSHA1(apiKey))
{
byte[] signatureBytes = hmac.ComputeHash(signature);
string hexSignature = BitConverter.ToString(signatureBytes).ToLowerInvariant().Replace("-", "");
Console.WriteLine(hexSignature);
session.Signature = hexSignature;
}

How to SHA-256 hash text in a chrome extension with SubtleCrypto

I am hashing a text field with Subtle Crypto and getting an [object ArrayBuffer].
The relevant code is here:
async function asyncCall() {
var enc = new TextEncoder(); // always utf-8
var enc2 = new TextDecoder(); // always utf-8
var digest3 = enc.encode(localStorage.getItem("Item 1"));
const digest2 = await crypto.subtle.digest("SHA-256", (digest3));
localStorage.setItem("Item Hashed", (digest2));
field2.value = localStorage.getItem("Item Hashed");
};
When I hash any text ("Item 1" is localStorage text that is defined with a text field) with this, I get [object ArrayBuffer] as the result. Why am I not getting something that looks like a SHA256 hash?
Convert ArrayBuffer to a Hex string:
const hashArray = Array.from(new Uint8Array(digest2)); // convert buffer to byte array
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string

Reassemble crypto hmac code in C#

I am trying to reassemble code in C# from JavaScript, Node js code.
I wrote fully working example in Node just to find out if the code is working correctly but now i am having problems with finding equivalent functions in C#.
JavaScript code using Node.js.
var crypto = require('crypto');
var timestamp = Date.now() / 1000;
var what = timestamp + "hello";
var secret = "SGVsbG8gV29ybGQ=";
var key = Buffer(secret, 'base64');
var hmac = crypto.createHmac('sha256', key);
hmac.update(what);
var t = hmac.digest('base64');
console.log(t);
I am only in need of knowing how to reassemble those functions:
var key = Buffer(secret, 'base64');
var hmac = crypto.createHmac('sha256', key);
hmac.update(what);
Here's a c# example. It includes a function. You would pass your timestamp info as the string I assume, but it can be done with any string.
https://dotnetfiddle.net/eAZGfE
public static string HashString(string StringToHash, string HachKey)
{
System.Text.UTF8Encoding myEncoder = new System.Text.UTF8Encoding();
byte[] Key = myEncoder.GetBytes(HachKey);
byte[] Text = myEncoder.GetBytes(StringToHash);
System.Security.Cryptography.HMACSHA1 myHMACSHA1 = new System.Security.Cryptography.HMACSHA1(Key);
byte[] HashCode = myHMACSHA1.ComputeHash(Text);
string hash = BitConverter.ToString(HashCode).Replace("-", "");
return hash.ToLower();
}

Generate Base64 MD5 hash of byte array

I have following security encoding implemented in my c# web api:
string testStr = "test";
ASCIIEncoding encoding = new ASCIIEncoding(); //using System.Text;
byte[] byteData = encoding.GetBytes(testStr);
MD5 md5 = MD5.Create(); //using System.Security.Cryptography;
string hash = md5.ComputeHash(byteData);
string md5Base64 = Convert.ToBase64String(hash);
I bind this md5Base64 string in header and compare it in API request. This works fine when I hit the API from C# code. Now I need to use it in javascript, so will need js equivalent of above code.
I have tried following but it is giving different output:
var testStr = 'test';
var byteData = testStr.split ('').map(function (c) { return c.charCodeAt (0); });
var hash = MD5(value.join(','));
var md5Base64 = btoa(hash);
the MD5 function used here is from https://stackoverflow.com/a/33486055/7519287
Please let me know what is wrong here.
The problem with your JavaScript code is that you're doing unnecessary conversions: MD5 already takes a string. Furthermore, more conversions after hashing are required.
If we have the following C# code:
string tmp = "test";
byte[] bTmp = System.Text.Encoding.UTF8.GetBytes(tmp);
byte[] hashed = null;
using (System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider())
{
hashed = md5.ComputeHash(bTmp);
}
Console.WriteLine(Convert.ToBase64String(hashed));
Fiddle
then the equivalent JavaScript code is:
var tmp = 'test';
var hashed = hex2a(MD5(tmp)); // md5 src: https://stackoverflow.com/a/33486055/7519287
// src: https://stackoverflow.com/a/3745677/3181933
function hex2a(hexx) {
var hex = hexx.toString();//force conversion
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
alert(btoa(hashed));
Fiddle
Because MD5 returns a hex string, you have to convert that to ASCII before you can base64 encode it. I wonder if you need base64 encoding? MD5 is usually represented as a hex string. Perhaps on the C# side, instead of Convert.ToBase64String(hashed), you could use BitConverter.ToString(hashed).Replace("-", "") to get a hex string for the MD5 hash? Then you could simply just use MD5(tmp) in JavaScript.

Categories

Resources