2014-03-06 48 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