【问题标题】:PHP - C# translated hashing function not working?PHP - C# 翻译的哈希函数不起作用?
【发布时间】:2017-06-11 02:57:39
【问题描述】:

我会直接回答这个问题,

我们有这段 C# 代码

using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, passwordSaltBytes, iterationCount))
 {
   pbkdf2Bytes = pbkdf2.GetBytes(derivedLength + iterationCountBytes.Length);         
 }

返回一个字节数组,第一个索引的值为252

我们在 PHP 中尝试同样的事情:

$key = hash_pbkdf2("SHA1", $password, $password.$salt, $iterationCount, 48); 

第一个索引是 102...

在这个特定部分之前的值都匹配。

只是那个散列函数没有给我一致的结果。

感谢您的帮助,干杯。

编辑 - 如果不是很明显,我试图理解为什么这两个值不匹配,我误解了什么编码/解码等等。

【问题讨论】:

  • pbkdf1 包括 sha1(向后兼容性),而 pbkdf2 不包括。请参阅:rfc-base.org/txt/rfc-2898.txt。另见发帖:stackoverflow.com/questions/8068133/…
  • 我昨天回答了一个可疑的熟悉问题。如果您阅读hash_pbkdf2 的文档,您会注意到的第一件事是它输出十六进制而不是原始数据,除非您将$raw_output 设置为true。你得到 102 的原因是因为 102 被编码为 ASCII/UTF8 中的字符 f。见这里:php.net/manual/en/function.hash-pbkdf2.php
  • @BarryD。为什么是$password.$salt 而不是$salt
  • @LukePark 和你来来回回的人不是 OP。但是我们知道您已经厌倦了帮助并删除了您的评论,不知道您为什么要在这里发帖-顺便说一句,您也可以随意删除这些 cmets。
  • @ArtjomB。因为 C# 脚本将两者结合起来并将其作为passwordSaltBytes 传递,在分析这些字节时,当我执行 $password.$salt 然后读取它们的字节时,我在 PHP 中得到相同的结果。

标签: c# php encryption rfc


【解决方案1】:

这是完整的 C# 代码。正如你所看到的,有一些不必要的循环等,但它不起作用的原因是 2:

  1. 正如有人指出的那样,默认情况下 PHP 中的字节不输出原始数据,因此其字节的散列(因此也是如此)与 C# 脚本的不完全相同。
  2. 以前,我认为(正如其他人也指出的那样)我应该传入$salt,因为它没有任何编码或转换。但是仔细观察实际的 C# 代码...我们可以在第二个 for i 循环中看到它们实际上是在 passwordBytes 上附加了 saltBytes,从而在 PHP 中创建了类似于 $password.$salt 的内容

结合以上两个问题:

  • 发送$password.$salt 而不是只发送一个,然后将$raw_output 选项设置为true,输出与C# 相同的哈希值和相同的字节。

        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
        byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
        byte[] iterationCountBytes = BitConverter.GetBytes(iterationCount);
        int derivedLength = passwordBytes.Length + saltBytes.Length;
        byte[] passwordSaltBytes = new byte[derivedLength];
        byte[] pbkdf2Bytes;
        string encryptedString;
    
    
        for (int i = 0; i < passwordBytes.Length; i++)
        {
            passwordSaltBytes[i] = passwordBytes[i];
        }
    
    
        for (int i = 0; i < saltBytes.Length; i++)
        {
            passwordSaltBytes[passwordBytes.Length + i] = saltBytes[i];
        }
    
        using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, passwordSaltBytes, iterationCount))
        {
            pbkdf2Bytes = pbkdf2.GetBytes(derivedLength + iterationCountBytes.Length);
    
    
        }
    

谢谢。

【讨论】:

    猜你喜欢
    • 2023-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 2012-10-04
    • 2012-04-29
    • 2015-12-02
    相关资源
    最近更新 更多