繁体   English   中英

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

[英]PHP and C# SHA256 Hashes returning different strings

因此,我发现了一个像这样的问题并得到了可接受的答案,因此我跳了起来,尝试实施必要的更改。 但是由于某种原因,我仍然得到两个不同的字符串,而且我不知道这是错的。 我试图评论已接受的答案以寻求帮助,但是我缺乏这样做的声誉。 所以,我想我会再问这个问题(那个问题也已经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了。

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

我正在使用的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从数据库加载哈希字符串和盐字符串,而我不得不使用那些sendStatusMessage方法来打印字符串,因为这是针对服务器应用程序的,该应用程序最多需要15分钟才能在调试模式下从数据库加载数据。 因此,我改为运行调试exe,因此不会运行Console.WriteLine调用。 newPlayer.password是存储在数据库中的哈希密码(使用php创建的密码)。 hPassword是使用我借用的C#方法计算得出的哈希值。

盐是e0071fa9,纯文本密码是“ test”。

这是我通过sendStatusMsg方法获得的结果:

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

关于我可能做错了什么的任何想法? 正如我之前所说,我只是在这里使用答案(几乎逐字借用代码),但仍然没有得到想要的结果。 这是我引用的问题: 为什么我的PHP SHA256哈希值不等同于C#SHA256Managed哈希值

因为作为您要链接的问题的答案, hash默认情况下会返回一个十六进制编码的字符串,而不是原始字节。 您将true作为第三个参数传递来覆盖对hash的外部调用的此行为,但对于内部调用则没有这样做。

实际上,为什么首先要有两个哈希? 内部哈希似乎根本没有任何作用。

正如乔恩(Jon)先前所述,php稍有缺陷。 如果有人尝试做这样的事情,请知道

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

相对于

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

产生巨大的变化。 php的第二行是达到目的的。

我希望这有帮助!

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

很好地了解password_hash在PHP中的工作方式(如果使用不支持它的PHP版本-请对其进行升级),您可以始终使用Anthony Ferrara兼容性库来获得良好的效果:

https://github.com/ircmaxell/password_compat

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

http://blog.ircmaxell.com/search/label/安全性

:)

暂无
暂无

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

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