C# SHA256 ComputeHash result different with Crypto

2019-04-12 07:42发布

I have a C# function as below:

string stringvalue = "530500480530490480530480480520570480520510500490";
var encodedvalue= Encoding.Unicode.GetBytes(stringvalue);
using (HashAlgorithm ssp = System.Security.Cryptography.HashAlgorithm.Create("SHA256"))
        {

            var digest = ssp.ComputeHash(encodedvalue);

            return BitConverter.ToString(digest); 

        }

I need to create a javascript function that match the code above so that the end result for both C# and JS is the same.

Currently in my JS code, I'm using this:

var hash = CryptoJS.SHA256("530500480530490480530480480520570480520510500490");
var hexhash = hash.toString(CryptoJS.enc.hex);

This is the result of my hexhash:

d956678c8f12c65299daf35019a9a1eb3e6eb9855fd850aeb5aafe46057d179e

But in my C# code, this line of var digest = ssp.ComputeHash(bPass); return the following array: enter image description here

I don't know much about encoding. Please tell me what type of result is being populated in the c# code above? If I'm not mistaken, the ComputeHash is returning bytes but I need lots of reading to confirm that which is another long hour of studying

I tried many different ways of converting the JS Sha256 code but no luck. I'm stuck at this particular line for almost a day.

Please help. Thanks

EDIT: Sorry for the code error. I had updated the C# code. ComputeHash accept an array

3条回答
The star\"
2楼-- · 2019-04-12 08:21

Try

var digest = ssp.ComputeHash(Encoding.UTF8.GetBytes(stringvalue))

return BitConverter.ToString(digest)
                   .Replace("-", string.Empty)
                   .ToLowerInvariant();

That js library is converting the string to UTF8 before calculating its hash.

查看更多
▲ chillily
3楼-- · 2019-04-12 08:24

In my example I am using System.Security.Cryptography.SHA256Managed to get SHA256 in C#.

The method SHA256Managed.ComputeHash takes a byte array as a parameter and return another byte array. Now we need to convert back your byte array to a string.

The following code return the same result a Javascript SHA-256.

 byte[] bytes = Encoding.UTF8.GetBytes("530500480530490480530480480520570480520510500490");
 SHA256Managed hashstring = new SHA256Managed();
 byte[] hash = hashstring.ComputeHash(bytes);
 string hashString = string.Empty;
 foreach (byte x in hash)
 {
     hashString += String.Format("{0:x2}", x);
 }
 return(hashString);

Just to explain : String.Format("{0:x2}", x)

  • X means Hexadecimal format.
  • 2 means 2 characters.
查看更多
做个烂人
4楼-- · 2019-04-12 08:27

I finally found the answer after uncountable hours of trial and error.

The C# code var digest = ssp.ComputeHash(encodedvalue) is returning byte array from the result of var encodedvalue= Encoding.Unicode.GetBytes(stringvalue); as Jean replied. In order to create the function in Javascript, I need to ensure that the encodedvalue is producing the correct encoding format and size just like the one in C#.

Using only CryptoJS, I manage to get the matching result from below

function GetHexFromString() {
var stringVal = '8563A578-7402-4567-A6CE-4DE4E0825B021234';
// Convert the string to UTF 16 little-endian
// Result: 560530540510650530550560450550520480500450520530540550450650540670690450520680690520690480560500530660480500490500510520
var utf16le = CryptoJS.enc.Utf16LE.parse(stringVal);  

// Convert to Sha256 format and get the word array
var utf16Sha256 = CryptoJS.SHA256(utf16le);
// Convert the Sha256 word array to Uint8Array to get the 32 byte array just to see the result to ensure it match with the C# function
// Result: 94,203,69,29,35,202,209,149,121,144,44,6,98,250,141,161,102,7,238,35,228,117,111,236,118,115,51,113,134,72,52,69
var utf16sha256Array = convertWordArrayToUint8Array(utf16Sha256); 

// Convert the Sha256 to hex (if i'm not mistaken, it's base 16) format
var hexSha256 = utf16Sha256.toString(CryptoJS.enc.hex);

 // Insert a dash in between 2 characters in the string
 hexSha256 = hexSha256.replace(/(\S{2})/g, "$1-");
 // Remove the last dash in the string
 hexSha256 = hexSha256.replace(/-$/, "");

// Final Result: 5E-CB-45-1D-23-CA-D1-95-79-90-2C-06-62-FA-8D-A1-66-07-EE-23-E4-75-6F-EC-76-73-33-71-86-48-34-45
return hexSha256.toUpperCase();
}

function convertWordArrayToUint8Array(wordArray) {
        var len = wordArray.words.length,
            u8_array = new Uint8Array(len << 2),
            offset = 0, word, i
        ;
        for (i = 0; i < len; i++) {
            var word = wordArray.words[i];                

            u8_array[offset++] = word >> 24;
            u8_array[offset++] = (word >> 16) & 0xff;
            u8_array[offset++] = (word >> 8) & 0xff;
            u8_array[offset++] = word & 0xff;                                              
        }
        return u8_array;
    }

Hope it help whoever that need such method

查看更多
登录 后发表回答