1

我使用 Crypto-JS v2.5.3 (hmac.min.js) http://code.google.com/p/crypto-js/库来计算客户端哈希,脚本是:

$("#PasswordHash").val(Crypto.HMAC(Crypto.SHA256, $("#pwd").val(), $("#PasswordSalt").val(), { asByte: true }));

这会返回如下内容:

b3626b28c57ea7097b6107933c6e1f24f586cca63c00d9252d231c715d42e272

然后在服务器端我使用下面的代码来计算哈希:

private string CalcHash(string PlainText, string Salt) {
        string result = "";
        ASCIIEncoding enc = new ASCIIEncoding();
        byte[]
        baText2BeHashed = enc.GetBytes(PlainText),
        baSalt = enc.GetBytes(Salt);
        System.Security.Cryptography.HMACSHA256 hasher = new HMACSHA256(baSalt);
        byte[] baHashedText = hasher.ComputeHash(baText2BeHashed);
        result = string.Join("", baHashedText.ToList().Select(b => b.ToString("x")).ToArray());
        return result;
    }

这个方法返回:

b3626b28c57ea797b617933c6e1f24f586cca63c0d9252d231c715d42e272

如您所见,服务器端方法忽略了一些零字符。哪里有问题?我的服务器端方法有什么问题吗?我只需要这两个值与相等的字符串和盐相同。

4

3 回答 3

4

如您所见,服务器端方法忽略了一些零字符。哪里有问题?

在这里-您在 C# 中转换为十六进制:

b => b.ToString("x")

如果b是 10,那只会给出“a”而不是“0a”。

我个人建议进行更简单的十六进制转换:

return BitConverter.ToString(baHashedText).Replace("-", "").ToLowerInvariant();

(您可以改为"x"改为"x2"指定 2 个字符的长度,但这仍然是一种执行字节到十六进制转换的迂回方式。)

于 2012-08-21T06:28:57.750 回答
2

其他人一直在推荐使用诸如使用 BitConverter 和修剪“-”或使用ToString(x2). 有一个更好的解决方案,一个自 1.1 SoapHexBinary以来就在 .NET 中的类。

using System.Runtime.Remoting.Metadata.W3cXsd2001;

public byte[] StringToBytes(string value)
{
    SoapHexBinary soapHexBinary = SoapHexBinary.Parse(value);
    return soapHexBinary.Value;
}

public string BytesToString(byte[] value)
{
    SoapHexBinary soapHexBinary = new SoapHexBinary(value);
    return soapHexBinary.ToString();
}

这将产生您想要的确切格式。

于 2012-08-21T06:52:29.087 回答
1

我相信问题出在这里:

result = string.Join("", baHashedText.ToList().Select(b => b.ToString("x")).ToArray());

将其更改为:

result = string.Join("", baHashedText.ToList().Select(b => b.ToString("x2")).ToArray());
于 2012-08-21T06:30:39.353 回答