2014-04-30 149 views
2

我創建一個基於PHP的CMS(使用MVC體系結構)。我想散列存儲在數據庫中的用戶密碼。我已經閱讀了許多有關這個主題的藝術品和教程,但我面臨着反對的意見/觀點和建議。我有點困惑。我正在尋找實現密碼散列的最佳方式。這些是我遇到的概念/方法:密碼哈希方法

首先,很多人混淆了單向哈希和雙向加密。如果我沒有弄錯,雙向加密是關於公私密鑰對的不對稱加密的問題,而且它是爲了保護數據並使其只能由知道其他密鑰(祕密密鑰)的人讀取。所以這就是我們現在不在乎的東西。

PHP提供了許多功能,以使散列,它們中的一些直接使用在給定的數據(md5()sha1()sha256()ripemd160()等)它們中的一些接受給定的數據和所支持的算法散列alogrithm和生成的哈希(hash(),hash_init(),hash_hmac()等) 哈希/加密方法的負載有什麼區別? (hash_pbkdf2(),crypt(),bcrpyt,password_hash()和其他以上提到的) 據我所知,在散列中使用鹽是一個好習慣,但多次散列是一個壞主意(即使如此多的散列也是好的)。有些功能的使用鹽別人用鑰匙...

問題1: 可能有人澄清什麼是如md5('myPassword');hash('md5', 'myPassword');(我知道MD5是一個容易破解的方法,不建議使用之間的:差異儲存口令)

問題2: ,是什麼關鍵之間的區別?那麼hash_hmac('sha1', 'myPassword', 'HaCK_MeIF_youCAN');sha1('myPassword'.'HaCK_MeIF_youCAN');之間有什麼區別? (注意hash_hamc調用它的第三個參數「鑰匙」)

問題3: 是多個散列真的是不好的做法? 像:

hash = sha512(password) 

for i in range(10000): 
    hash = sha512(hash) + salt 

return hash 

問題4: 應該用什麼來散列我的密碼的最佳方法是什麼?

由於這是一個重要和敏感​​的問題,我認爲其他人不熟悉像我這樣的話題想要使這個哈希事情清楚,希望一勞永逸得到準確和可靠的答案,我請你回答以防萬一您是IT安全專家,或者您擁有此主題的任何認證或學位! (對於誰收購了互聯網上的知識自稱安全專家:事實上你已經做了數百個散列密碼系統/網站,並不意味着他們是安全的!)

而最後一個請求:簡單(初學者)web程序員不是外星人,也不是理論數學家。所以請嘗試在一些像人一樣的英語中解釋:)

+1

您是否閱讀過[基於網站認證的權威指南](http://stackoverflow.com/questions/549/the-definitive-guide-to-form-b​​ased-website-authentication)? –

+2

問題4:使用'password_hash'或其兼容性庫。這是一個易於使用bcrypt封裝。 – CodesInChaos

+0

另請參閱Openwall的[便攜式PHP密碼哈希框架](http://www.openwall.com/phpass/)(PHPass)。它強化了對用戶密碼的一些常見攻擊。 – jww

回答

0

我會盡量回答你的一些問題,但首先關於加密的一句話。加密的問題在於它是雙向的,如果您知道密鑰,則可以檢索密碼。僅存儲散列(單向)將更好地保護密碼,因爲即使已知所有代碼(包括密鑰),也無法檢索密碼。

問題1 & 2: 這是你避免所有的快速散列算法很重要,這包括MD5,SHA *。因爲它們速度如此之快,所以它們可能很容易被蠻橫逼迫。它是例如可以使用通用硬件計算每秒鐘的8 Giga MD5哈希值。

問題2: 的鹽應爲每個密碼是隨機產生的,但並不是祕密,並且可以存儲明文與數據庫中的密碼。一個密鑰(有時稱爲胡椒)應該保密並且不存儲在數據庫中。

問題3: 多哈希是一件好事,但只有在正確完成的情況下。像BCrypt和PBKDF2這樣的適當算法以安全的方式進行,並且它們具有確定迭代次數的成本因素。這個成本因素可以適應未來和更快的硬件。

問題4: 此刻的你能做的最好是使用PHP函數password_hash()創建BCrypt哈希值。對於早期版本,還有一個compatibility pack。我寫了一個關於安全存儲密碼的tutorial,在那裏我試圖回答這個問題更深入一點,希望能夠理解的形式,所以你可以看看它。

+0

由於AC已經感到困惑,我會對條款挑剔。根據定義,*加密*總是雙向的,沒有「單向加密」之類的東西。這將被稱爲*單向哈希*(或*一般函數*)。非常不幸的是,有很多消息來源談到「密碼加密」時,他們真的想說「密碼散列」。 – Perseids

+0

@Perseids - 這實際上是我寫的,我認爲如果它被明確提及,它會使事情更清楚。無論如何,我試圖稍微改寫它。 – martinstoeckli

+0

您對本教程的一些反饋感興趣嗎? – Perseids

2

在Stack Exchange上有很多關於密碼哈希的問題,所以這基本上是一個重複的問題,但是因爲你不知道要相信什麼,所以我會給你一些指示。

回覆:問題1:可能它們對於相同的代碼只是不同的接口。 (我還沒有檢查,雖然如果你想確保把相同的輸入兩個和比較輸出或只是仰望在源代碼中的文檔或。)

回覆:問題2:一密鑰是私密信息,您通常不應該公佈(公鑰在非對稱密碼術中除外)。密碼散列通常沒有密鑰。鹽是一種隨機的公共信息,意味着將密碼哈希與世界上其他所有預先計算的哈希表區分開來。這是對rainbow tables的主要防禦。

HMAC(基本上m,kHash(k||Hash(k||m))爲並置運算||)被設計爲所謂的message authentication code。它是(ab)用於許多其他目的,因爲它的多功能設計,如果用一個好的加密散列函數實例化。在這種情況下,使用salt作爲密鑰並將密碼用作HMAC中的消息與Hash(password||salt)確實沒有什麼不同。

回覆:問題3:不,這是一個很好的做法。密碼存儲的主要攻擊方案是您的數據庫受到攻擊(如果您的數據足夠重要以至於所有密碼數據都會發布,那麼人們會關注)。大多數非技術人員(顯然甚至一些具有IT背景的人)經常重複使用他們的密碼(即使每個人都會得到他們的密碼哈希海峽,這也是bad practice)。因此,如果您將密碼保存爲純文本,那麼在數據庫違規的情況下,很多人的帳戶突然知道登錄信息。爲了防止這種情況,您希望對密碼使用單向函數。不幸的是,大多數時候密碼的熵很少(因爲沒有人喜歡記住密碼安全的密碼),因此如果你使用快速哈希函數,你可以嘗試每個可能的密碼並將哈希與數據庫中的密碼進行比較。作爲一個極端的例子,假設我只使用密碼catdog,並且您的密碼爲sha1 hash:8f6abfbac8c81b55f9005f7ec09e32d29e40eb40echo $password | sha1sum生成。爲讀者練習:使用哪個密碼?

爲了緩解這個問題,您希望使用慢哈希函數,以便嘗試使用每個可能的密碼需要很長時間。減緩哈希的一種方法是迭代哈希數千次(甚至數十萬次)。然而,其他緩慢的散列概念,如bcrypt,不只是迭代散列。

回覆:問題4:可以在security.stackexchange.com上找到深入的討論:https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords。 tl,dr版本是CodeInChaos的評論:只需使用password_hash,它大多是傻瓜證明。除了鹽之外,還可以找到辣椒先進主題的資源:https://security.stackexchange.com/a/3289/10727