2010-01-26 227 views
11

我讀過一些問題,它們建議散列密碼並將它們存儲在數據庫中。加密密碼

當某人登錄時,會散列提供的密碼與您存儲的密碼。

我不明白的是這是如何工作的?兩個字符串可以哈希到相同的值 - 不可能,但肯定有可能

有人可以幫助我嗎?

編輯:任何人都可以給出一個統計的碰撞可能性?

+0

我在大約生日攻擊的答覆中提到: http://en.wikipedia.org/wiki/Birthday_attack 它會給你提供的一個碰撞的相似性嘗試次數和可能的散列數(基於位)。這是一個暴力攻擊。如果哈希值可能會「破」,則可能性更高 – Vanwaril 2010-01-26 15:26:21

+0

http://stackoverflow.com/questions/615704/preferred-method-of-storing-passwords-in-database – erickson 2010-01-26 15:50:15

+0

您可能會發現我關於此主題的一系列文章有趣讀。 http://blogs.msdn.com/ericlippert/archive/tags/Salt/default.aspx – 2010-01-26 19:25:33

回答

24

您不應該存儲未加密的密碼,因爲您的數據庫管理員不應該訪問客戶密碼。

散列密碼可防止數據庫管理員看到密碼。

碰撞的可能性非常小並不是問題,因爲這不會顯着增加某人試圖在鎖定帳戶之前強制客戶密碼獲得匹配的機會。

PS它也是很好的做法散列,使之更加仍然難以蠻力如果黑客不知怎麼進入密碼錶之前的密碼。使其更難以使用彩虹表等。

+6

爲了最大限度地減少多重暴力攻擊的風險密碼你也應該鹽他們。 – Joey 2010-01-26 14:49:31

+7

密碼沒有太多味道;鹽他們總是。 – Will 2010-01-26 14:58:33

+2

我發現,觸摸辣椒也會增加一些咬痕。 – 2010-01-26 15:00:53

1

散列函數的開發必須使得對於2個不同的輸入不可能給出相同的散列,即它是抗碰撞的。更多信息請見wikipedia

2

你可以說「絕對可能」,因爲它可能是可能的,但是用一個好的散列算法,這是極不可能的。有大量關於選擇散列算法的文章可供選擇,並且衝突率是選擇過程中的一個重要因素。

人們提倡散列與加密的原因是因爲散列是單向操作。碰撞的可能性是從用戶安全角度出發的一種很好的選擇。因爲兩個值可以產生相同的散列值,所以散列值不能顛倒。這使得某人無法(或幾乎不可能)侵入您的數據庫並獲得其他站點的登錄憑據(因爲用戶在您的系統中經常使用與他人一樣的密碼)。

5

即使兩個字符串可以散列到相同的值(並且它們確實是這樣做的,因爲可能值的空間比散列空間大得多),但找到這樣的字符串對仍然不是那麼容易(前提是你使用強大的散列函數)。

因此,如果攻擊者想要在不知道密碼的情況下以其他人身份登錄,他必須找到一個密碼,該密碼具有相同的散列,應該與查找密碼一樣困難(散列函數的不可逆性爲一個基本屬性)。

如果你想使用散列。NET,嘗試像

public static string ComputeHash(string plaintext) 
    { 
     HashAlgorithm mhash = new SHA1CryptoServiceProvider(); 
     byte[] bytValue = Encoding.UTF8.GetBytes(plaintext); 
     byte[] bytHash = mhash.ComputeHash(bytValue); 
     mhash.Clear(); 
     return Convert.ToBase64String(bytHash); 
    } 
10

兩個字符串可以返回相同的值 - 不太可能,但絕對有可能

是的,但如果哈希是足夠大,質量好,它的不太可能不擔心。用口語來說:應用程序的每個用戶同時遭到閃電擊中都不是很好,但絕對可能是。你擔心這個嗎?

+10

太棒了,現在又擔心另一件事了。謝謝。 – badideas 2010-01-26 15:02:40

+0

你必須乘風險後果。如果系統管理員(或黑客)與用戶具有相同的密碼,他們將看到他們的哈希值和密碼相同,並且能夠以該用戶身份登錄。如果你正在建立一個銀行網站,這就成了一個問題。 – 2010-01-26 15:09:48

+0

@Rob:這就是爲什麼你追加隨機鹽。不僅兩個相同密碼的哈希值會不同,他們將更難以破解。 – 2010-01-26 15:14:50

0

使用適當的散列算法,碰撞的機率非常小。只要你能一致地計算哈希,不管兩個字符串碰巧是否具有相同的哈希(只要它不經常發生)都沒有關係。您只是將用戶輸入的密碼的哈希與存儲在數據庫中的哈希進行比較。

1

這是一個很好的實現。

private static string CreateSalt(int size) 
    { 
    //Generate a cryptographic random number. 
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
    byte[] buff = new byte[size]; 
    rng.GetBytes(buff); 

    // Return a Base64 string representation of the random number. 
    return Convert.ToBase64String(buff); 
    } 

private static string CreatePasswordHash(string pwd, string salt) 
    { 
    string saltAndPwd = String.Concat(pwd, salt); 
    string hashedPwd = 
    FormsAuthentication.HashPasswordForStoringInConfigFile(
    saltAndPwd, "sha1"); 

    return hashedPwd; 
    } 

來源:http://davidhayden.com/blog/dave/archive/2004/02/16/157.aspx

0

採取例如MD5散列串 - 它具有128位,這意味着可產生2^128個不同的哈希值。即使考慮到Birthday Paradox,它是極不可能一個字符串是不是真正的密碼可以被發現生成的哈希值(當然,MD5已被發現不安全,但這是另一個問題,MD5只是一個例)。

所以說你有一個密碼,程序哈希它,並把散列在數據庫中。當你嘗試登錄時,你輸入的內容被散列並對照該散列進行檢查 - 如果這是一個猜測,那麼你有一個2 * 128的概率,你是正確的。這是無限小的,並且以這種方式真正破解密碼(蠻力)是'不可行的'。增加比特數量,除非散列算法至少可以部分反向設計,否則它實際上變得不可能。

4

你所說的被稱爲「碰撞脆弱性」。但首先有一點背景。

如果您存儲了未加密的密碼,那麼這是一個安全漏洞,正如您可能猜到的那樣,Sam建議。但是,您可以使用經過驗證的算法,從而降低這種可能性。你絕對不應該嘗試發明自己的(因爲你似乎不是算法開發者)。

我通常使用MD5,它可以在諸如mysql之類的數據庫中使用。這樣,您也可以將檢查嵌入到數據庫查詢中。

現在,MD5不幸的是不是碰撞抵抗。然而,碰撞的機會非常渺茫。在留言板上可能會有其他建議,您可以查看。我知道SHA-2就是這樣一種可能性。我不知道在應用程序中使用它有多簡單。

+0

碰撞漏洞是一個漏洞,其中發現兩個消息,一個是無辜的,一個是敵對的,具有相同的散列。您能否解釋碰撞漏洞如何與用戶關於密碼的問題相關?因爲我沒有在這裏遵循你的思路。 – 2010-01-27 19:57:45

+0

對我來說,這個問題被翻譯成「可以用兩個不同的字符串創建相同的散列」。我最近發現在MD5中它是可能的。現在,其他一些用戶指出,你不需要密碼是唯一的。但是在一些域中(比如我的當前域),你不會輸入用戶名,所以密碼應該是唯一的。在這種情況下,避免具有碰撞漏洞的散列函數。實際上,碰撞的可能性很小,MD5仍然可以工作99.99%的時間。這比原來的答案更有意義嗎? – Tanmay 2010-01-28 12:35:04

1

儘管碰撞機會可能很渺茫(取決於你的散列算法,「slimness」),它並不重要,是嗎?

即使您對用戶x和用戶y具有相同的密碼哈希值,也永遠不會比較兩個用戶的密碼以確定它們是基於哈希值的相同密碼!因此,儘管'技術上'是一種碰撞哈希,但在這種情況下它並不真正碰撞/干擾/重要。

1

是的,這是可能的,但不太可能有一個體面的散列。

給你一個例子:SHA1是160位,意思是找到兩個字符串具有相同的散列,你需要散列2^80個不同的字符串。即使我們所有的最好的超級計算機,沒有人有有史以來發現兩個字符串哈希到相同的SHA1值(雖然我預測它會很快發生)。

3

說: 「MyAwesomePassword1」 與事實 「@@#$ ngt0n8 !! ~~~ 09 || {2` = &! - [kla2%B Q」 將返回相同的值不是一個安全漏洞。

1

如果您擔心碰撞,請使用512位的SHA-2。再次,SHA-1算法還沒有得到證明的碰撞,所以它仍然足夠安全,不用擔心碰撞。

0

如果你用體面種子使用SHA-512,這種情況發生的可能性不大(但不是不可能)。

布魯斯·沙伊納對各種安全技術的健壯性一些有趣的博客 - sha1 broken

另一個考慮是確保兩個用戶使用相同的密碼,他們沒有使用相同的散列結果在數據庫中結束。

爲了解決這個問題,您可以構建一個種子,其中包含特定於用戶的內容,如用戶表中的用戶ID鍵字段。

0

爲什麼多個字符串會散列到相同的密碼值?每次用戶輸入他或她的密碼時,它都會哈希到相同的值,並且會對用戶進行身份驗證。輸入幾乎任何其他密碼幾乎肯定不會與哈希值相匹配。如果你使用的是一個好的哈希函數,它提供了一個64位的值,那麼另一個密碼與用戶匹配的可能性大約是一個密碼。

你在防範的是內部人員複製用戶密碼,並且如果安全性被破壞並且密碼錶受到威脅,則顯示實際的密碼。標準技術是向密碼添加一些額外的位(salt,每個帳戶應該不同),並使用強大的散列函數。

如果你這樣做,很難找到一個能產生給定散列的密碼,除非你在密碼後嘗試輸入密碼,直到你找到了正確的密碼。哈希以這種方式爲內部人員和入侵者提供保護:訪問密碼錶不足以作爲其他人登錄。

有可能兩個用戶具有相同的密碼,或者(儘管這是極不可能的)密碼散列爲相同的值。用鹽,它們在密碼錶中看起來不會相似,所以沒有入侵者或內部人員通過查看錶格來知道他們的密碼與其他人的密碼相同。

另一個好處是許多人重複使用密碼,特別是對於不需要安全的帳戶。 (我所有的財務信息帳戶都有不同的密碼,但我在各種論壇上使用的密碼並不那麼強)。使用salt和hash時,無法確定我的密碼是否與站點A上的密碼相同現場B,即使有兩個密碼錶。

0

即使md5()和sha1()及類似的函數實質上是執行散列的加密函數,散列和加密也是略有不同的概念。由於理論上的哈希應該爲給定的輸入(通常是較大的尺寸)提供獨特的輸出,所以它基本上意味着每個哈希應該映射到單個輸入 - 這意味着您手上有一個完美的壓縮函數,通常可以減少大小爲N的數據大於M的數據到這樣大小的數據M,並且該過程是可逆的。但是,實際上會發生哈希碰撞。這意味着一個散列可能會映射到多個原始輸入。這意味着一個密碼哈希可能會爲您提供一個完全不同的密碼的用戶,這是一個真正的安全問題。

然而,加密保證是可逆的(當然有正確的解密密鑰),其中加密數據與原始數據具有一對一的關係。如果您的密碼長度爲N,那麼您的加密密碼也是大小N.密碼同樣安全並且沒有衝突。正如他們所說,如果某件事情太好而不真實,那很可能是 - 如果散列可以是可逆的以總是產生原始數據,那麼我們就不需要數據壓縮算法 - 我們可以將任意大小的數據,散列它會產生一些128位長的數據,並期望它在需要時恢復原始數據。然而,這並不是如此。你的原始數據越長,散列越不可靠,不管它的長度如何。

創建加密/解密密鑰對,並在將用戶的密碼存儲到公共位置之前對其進行加密。

0

碰撞確實發生,但它們應該足夠稀少,以至於不可能在一定的時間內發生碰撞。

這些天的大多數攻擊都考慮到所用算法的弱點,因此可以更快找到要利用的衝突。顯示MD5比先前認爲的要弱。 The Register的這個article顯示了這個弱點是如何被用來創建SSL證書的。

更多的抗性算法已被證明有缺陷,可以更容易地找到這些衝突。

PDF這個PDF顯示了一篇論文討論SHA-1 collisons以及它如何變得更容易。 (數學重)

出於實用的目的有人試圖恢復從哈希工具的密碼,如彩虹表採用

http://project-rainbowcrack.com/

這是考慮到,人們會選擇那些易於密碼,所以它的使用dictionary attack(常用密碼列表以及許多其他術語)來計算哈希值並對它們進行比較。這就是爲什麼使用salt總是建議