2014-03-06 49 views
1

所以,我发现一个问题就像这个接受的答案,所以我跳了下去,并试图实施必要的更改。由于某种原因,我仍然得到两个不同的字符串,我不知道我做错了什么。我试图对接受的答案发表评论以寻求帮助,但我缺乏这样做的声誉。所以,我想我会再次提出这个问题(这个问题也是2岁)。PHP和C#SHA256散列返回不同的字符串

让我解释我在做什么。

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

盐是e0071fa9,明文密码是'test'。

这是结果,我与sendStatusMsg方法获得:

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

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

+0

不要创建yourownpassword散列方法。取而代之的是使用一个函数,例如'PBKDF2','Rfc2898DeriveBytes','password_hash','Bcrypt'或类似的函数,CPU时间约为100ms。关键是要让攻击者花费大量时间通过强力查找密码。强制性的:[“Schneier's Law”](https://www.schneier.com/blog/archives/2011/04/schneiers_law.html):任何人,从最无知的业余爱好者到最好的密码学家,都可以创建一个算法,他自己不能打破。 – zaph

回答

0

因为作为您要链接的问题的答案,hash默认返回一个十六进制编码的字符串,而不是原始字节。您将通过true作为第三个参数来覆盖外部呼叫hash的这种行为,但您对内部呼叫的做法并不相同。

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

+0

只是想匹配我读的代码。我是一个PHP noob,所以我只是复制它。我想回去并删除内部的哈希电话。我会看看那是什么。 – Silver

+0

哇。你说的是错误。具有真实参数的第二个散列调用突然解决了世界上所有的问题。 – Silver

+0

@银:由于答案很有用,请点击复选标记接受它。 – Jon

0

正如乔恩在前面所说,php有点小故障。如果其他人试图做这样的事情,知道

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

,而不是

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

使一个巨大的差异。 PHP的第二行是诀窍。

我希望这有助于!

-1

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

对PHP中如何password_hash作品很好看(如果使用的PHP版本不支持它 - 请升级它),你可以随时使用安东尼费拉拉兼容性库效果好:

https://github.com/ircmaxell/password_compat

如果你按照他的博客,您将获得有关这些问题的一些提示岌岌可危:

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

:)

+0

安全/加密专家不会使用他们自己的哈希机制,他们知道比这样做更好。 BTW:倒票不是我的,但它是一个迟到的答案。 – zaph