PHP和C#SHA256哈希返回不同的字符串

时间:2014-03-06 09:35:09

标签: c# php hash sha256

所以,我发现了一个像这样的问题并且接受了答案,所以我跳了下来,试图实施必要的改变。出于某种原因,我仍然得到两个不同的字符串,我不知道它是什么我做错了。我试图评论找到帮助的公认答案,但我缺乏这样做的声誉。所以,我想我会再次提出这个问题(这个问题也是2年了)。

让我解释一下我在做什么。

在php ...

$intermediatesalt = md5(uniqid(rand(), true));
$salt = substr($intermediatesalt, 0, 8);
$hashpassword = base64_encode(
hash('sha256', $salt . hash('sha256', $password), true)
);

表示$ hashpassword的行取自此问题的接受答案。我没有写任何这个php,我的朋友做了。我只知道编程改变代码,但我无法在php中创建任何内容,更不用说HTML了。

创建哈希后,哈希和salt都存储在数据库中。

我正在使用的C#方法也来自我在这里找到的答案。

    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;
    }

但是出于某些奇怪的原因,即使提出问题的人得到了他/她想要的东西,我仍然会得到一个不受欢迎的结果。

这是加载播放器数据的代码块,然后将php生成的散列密码与c#生成的散列密码进行比较。

        // load the player based on the given email
        PlayerStructure.Player newPlayer = MySQL.loadPlayer(email);

        // compute a hash based on the given password and the retrieved salt
        // then, compare it to the hashed password on the database
        string hPassword = Program.ComputeHash(password, newPlayer.salt);

        if (newPlayer.password != hPassword)
        {
            sendStatusMsg(index, "Invalid password.");
            sendStatusMsg(index, "1: " + hPassword);
            sendStatusMsg(index, "2: " + newPlayer.password);

            return;
        }

MySQL.loadPlayer从数据库加载哈希字符串和salt字符串,我不得不使用那些sendStatusMessage方法来打印字符串,因为这是用于服务器应用程序,在调试中从数据库加载数据最多需要15分钟模式。所以我改为运行debug exe,而不是调用Console.WriteLine。 newPlayer.password是存储在数据库中的散列密码(用php创建的密码)。 hPassword是使用我借用的C#方法计算的哈希值。

salt是e0071fa9,纯文本密码是'test'。

这是我使用sendStatusMsg方法得到的结果:

Invalid password.
1: 3QQyVEfmBN4kJJHsRQ307TCDYxNMpc4k3r3udBaVz8Y=
2: moHRVv9C0JvpdTk28xGm3uvPPuhatK2rAHXd5he4ZJI=

关于我可能做错的任何想法?正如我之前所说,我实际上只是在这里使用了答案(几乎逐字地借用代码)并且我仍然没有得到我想要的结果。这是我引用的问题:Why isn't my PHP SHA256 hash equivalent to C# SHA256Managed hash

3 个答案:

答案 0 :(得分:0)

因为作为问题的答案,你链接到说,hash默认返回十六进制编码的字符串而不是原始字节。您正在传递true作为第三个参数,以覆盖对hash的外部调用的此行为,但您不会对内部调用执行相同的操作。

事实上为什么首先有两个哈希?内部哈希似乎没有任何用途。

答案 1 :(得分:0)

正如乔恩先前所说,php有点缺陷。如果其他人试图做这样的事情,那就知道了

$hashpassword = base64_encode(
hash('sha256', $salt . hash('sha256', $password), true)
);

而不是

$hashpassword = base64_encode(
hash('sha256', $salt . hash('sha256', $password, true), true)
);

有很大的不同。 php的第二行就是诀窍。

我希望这有帮助!

答案 2 :(得分:-1)

请在PHP上避免使用自己的散列机制,除非您是安全/加密专家(更重要的是,知道您在做什么)。

详细了解password_hash如何在PHP中运行(如果使用不支持它的PHP版本 - 请升级它),您可以随时使用Anthony Ferrara兼容性库以获得良好的效果:

https://github.com/ircmaxell/password_compat

如果您关注他的博客,您将获得有关所涉及问题的一些提示:

http://blog.ircmaxell.com/search/label/Security

:)