为什么我的PHP SHA256哈希不等同于C#SHA256Managed哈希

Why isn't my PHP SHA256 hash equivalent to C# SHA256Managed hash

为什么这些不一样?

PHP:

1
    $hash = hash('sha256', $userData['salt'] . hash('sha256', $password) );

C.*

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    public static string ComputeHash(string plainText, string salt)
    {
        // Convert plain text into a byte array.
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
        byte[] saltBytes = Encoding.UTF8.GetBytes(salt);

        SHA256Managed hash = new SHA256Managed();

        // Compute hash value of salt.
        byte[] plainHash = hash.ComputeHash(plainTextBytes);

        byte[] concat = new byte[plainHash.Length + saltBytes.Length];

        System.Buffer.BlockCopy(saltBytes, 0, concat, 0, saltBytes.Length);
        System.Buffer.BlockCopy(plainHash, 0, concat, saltBytes.Length, plainHash.Length);

        byte[] tHashBytes = hash.ComputeHash(concat);

        // Convert result into a base64-encoded string.
        string hashValue = Convert.ToBase64String(tHashBytes);

        // Return the result.
        return hashValue;
    }


C正在输出base64编码字符串,而php正在输出十六进制数。更好的比较方法是将参数true传递到php和base64的哈希函数的末尾,结果是:

1
2
3
 $hash = base64_encode(
           hash('sha256', $userData['salt'] . hash('sha256', $password), true )
         );


因为它们是不同的。您的C代码在末尾用base64编码对计算出的哈希进行编码。php只返回十六进制数字的字符串。


第一嫌疑犯:

1
Encoding.UTF8.GetBytes(plainText);

C使用UTF-8,您的PHP可能不使用,但如果您严格使用US-ASCII子集中的字母,您可能会很幸运。

第二嫌疑犯:

1
Convert.ToBase64String(tHashBytes);

在PHP中没有关于base64的内容。

因为PHP会给您一个十六进制编码的结果,所以您也应该在C中切换到十六进制。有关解决方案,请参阅此答案。


嗯,我不是C程序员,但有一件事让我大吃一惊:

1
2
// Convert result into a base64-encoded string.
string hashValue = Convert.ToBase64String(tHashBytes);

您是否使用C对最终输出进行base64编码?因为你不在PHP中…


1
2
3
4
5
6
7
C#
string toHash ="abcdefg";
SHA256Managed hash = new SHA256Managed();
byte[] signatureData = hash.ComputeHash(new UnicodeEncoding().GetBytes(toHash));
string hashResult = System.Convert.ToBase64String(signatureData);
PHP
print base64_encode(hash("sha256",mb_convert_encoding("abcdefg","UTF-16LE"),true));

写得像顶级代码,它们是一样的