简体   繁体   English

C# SHA256 ComputeHash 结果与 CryptoJS SHA256 不同 function

[英]C# SHA256 ComputeHash result different with CryptoJS SHA256 function

I have a C# function as below:我有一个 C# function 如下:

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.我需要创建一个 javascript function 匹配上面的代码,这样 C# 和 JS 的最终结果是相同的。

Currently in my JS code, I'm using this:目前在我的 JS 代码中,我正在使用这个:

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

This is the result of my hexhash:这是我的 hexhash 的结果:

d956678c8f12c65299daf35019a9a1eb3e6eb9855fd850aeb5aafe46057d179e

But in my C# code, this line of var digest = ssp.ComputeHash(bPass);但是在我的 C# 代码中,这行var digest = ssp.ComputeHash(bPass); return the following array:返回以下数组: 在此处输入图像描述

I don't know much about encoding.我对编码了解不多。 Please tell me what type of result is being populated in the c# code above?请告诉我上面的 c# 代码中填充的是什么类型的结果? 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如果我没记错的话,ComputeHash 正在返回字节,但我需要大量阅读才能确认这又是一个漫长的学习时间

I tried many different ways of converting the JS Sha256 code but no luck.我尝试了许多不同的方法来转换 JS Sha256 代码,但没有成功。 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.我已经更新了 C# 代码。 ComputeHash accept an array ComputeHash 接受一个数组

In my example I am using System.Security.Cryptography.SHA256Managed to get SHA256 in C#. 在我的示例中,我使用System.Security.Cryptography.SHA256Managed在C#中获取SHA256。

The method SHA256Managed.ComputeHash takes a byte array as a parameter and return another byte array. SHA256Managed.ComputeHash方法将一个字节数组作为参数,并返回另一个字节数组。 Now we need to convert back your byte array to a string. 现在我们需要将您的字节数组转换回字符串。

The following code return the same result a Javascript SHA-256. 以下代码返回相同的结果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) 只是为了解释:String.Format(“{0:x2}”,x)

  • X means Hexadecimal format. X表示十六进制格式。
  • 2 means 2 characters. 2表示2个字符。

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); C#代码var digest = ssp.ComputeHash(encodedvalue)var encodedvalue= Encoding.Unicode.GetBytes(stringvalue);的结果返回字节数组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#. 为了在Javascript中创建函数,我需要确保encodedvalue生成正确的编码格式和大小,就像在C#中一样。

Using only CryptoJS, I manage to get the matching result from below 仅使用CryptoJS,我设法从下面获得匹配结果

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 希望它能帮助那些需要这种方法的人

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. 该js库在计算其哈希值之前将字符串转换为UTF8。

An alternative to Koo SengSeng's answer (if you don't want to use CryptoJS library). 替代Koo SengSeng的答案(如果你不想使用CryptoJS库)。
SHA256 function is from here , the arrToUintArr function is from Koo SengSeng's answer. SHA256函数就是从这里开始的arrToUintArr函数来自Koo SengSeng的答案。

var SHA256=function a(b){function c(a,b){return a>>>b|a<<32-b}for(var d,e,f=Math.pow,g=f(2,32),h="length",i="",j=[],k=8*b[h],l=a.h=a.h||[],m=a.k=a.k||[],n=m[h],o={},p=2;64>n;p++)if(!o[p]){for(d=0;313>d;d+=p)o[d]=p;l[n]=f(p,.5)*g|0,m[n++]=f(p,1/3)*g|0}for(b+="\x80";b[h]%64-56;)b+="\x00";for(d=0;d<b[h];d++){if(e=b.charCodeAt(d),e>>8)return;j[d>>2]|=e<<(3-d)%4*8}for(j[j[h]]=k/g|0,j[j[h]]=k,e=0;e<j[h];){var q=j.slice(e,e+=16),r=l;for(l=l.slice(0,8),d=0;64>d;d++){var s=q[d-15],t=q[d-2],u=l[0],v=l[4],w=l[7]+(c(v,6)^c(v,11)^c(v,25))+(v&l[5]^~v&l[6])+m[d]+(q[d]=16>d?q[d]:q[d-16]+(c(s,7)^c(s,18)^s>>>3)+q[d-7]+(c(t,17)^c(t,19)^t>>>10)|0),x=(c(u,2)^c(u,13)^c(u,22))+(u&l[1]^u&l[2]^l[1]&l[2]);l=[w+x|0].concat(l),l[4]=l[4]+w|0}for(d=0;8>d;d++)l[d]=l[d]+r[d]|0}for(d=0;8>d;d++)for(e=3;e+1;e--){var y=l[d]>>8*e&255;i+=(16>y?0:"")+y.toString(16)}return i};
var arrToUintArr=function(a){for(var l=a.length,b=new Uint8Array(l<<2),o=0,w,i=0;i<l;i++) w=a[i],b[o++]=w>>24,b[o++]=(w>>16)&0xff,b[o++]=(w>>8)&0xff,b[o++]=w&0xff;return b;}
var computeHash=function(k){for(var a=[],s=SHA256(k),i=0;i<8;i++) a.push(parseInt(s.substr(i*8,8),16));return arrToUintArr(a);}

computeHash(k) will return an array of numbers representing bytes. computeHash(k)将返回表示字节的数字数组。

This is equal to below code in C#: 这等于C#中的以下代码:

new System.Security.Cryptography.SHA256CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(k));

typescript code:打字稿代码:

private computeHash(text: string): string {
    return CryptoJS.SHA256(text).toString();
}

c# equivalent: C# 等效:

private string ComputeHash(string text)
{
    using (var sha256 = SHA256.Create())
    {
       var bytes = Encoding.UTF8.GetBytes(text);
       var hash = sha256.ComputeHash(bytes);
       return hash.Aggregate(string.Empty, (current, x) => current + $"{x:x2}");
    }
}

after two days of research it works perfectly.经过两天的研究,它完美地工作。 Two different codes give the same result.两个不同的代码给出相同的结果。

js js

const sha1 = require('sha1');    
const getHash = str =>{
    const hashingBytes = Buffer.from(sha1(str), "hex");
    const base64Value = Buffer.from(hashingBytes).toString('base64');
    return base64Value;
}

c# c#

 System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
        byte[] bytes = System.Text.Encoding.ASCII.GetBytes(str);
        byte[] hashingbytes = sha.ComputeHash(bytes);
        var hash = Convert.ToBase64String(hashingbytes);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM