來源:http://www.server110.com/sec_news/201309/995.html
html
這段時間諸多爆庫的新聞,裏面有許多饒有趣味的事情。那些用簡單密碼,或者一個密碼走天下的笑話就不說了,咱說點有內涵的。(這篇文章是給IT界的人看的,若是你看不懂,我會準備一個簡單的「如何辨別密碼安全糟糕的網站」的方法給你,另文描述。)爆庫以後哀鴻遍野,一大堆人都在裏面嗷嗷亂叫,固然也包括我在內。可是當我嗷了一陣子以後,發現個人G點和你們的竟然不同,就靜下心來觀察。結果發現就連大多數IT界的人對密碼學這個玩意兒竟然都是一無所知的狀態,各類人云亦云的笑話此起彼伏。固然了,能看懂的也沒幾個。
就好比說MD5不安全這個笑話。
其實也不知道這怎麼就跟爆庫的事情扯到一塊去了,但總歸那幾天就有一堆人上來恨恨地說:MD5不安全,如今還有人用來作密碼的散列……好吧,大概對於有些人來講有點深了,這個知識之後我補。咱接着說,「簡直是遜爆了」。固然,原文不是如此,但也差很少了。
言下之意,就是他的知識告訴他MD5是不安全的,而用這些的人大概是沒知識的。而事實上是,這麼說的人一樣沒有知識。爲何?首先要搞清楚所謂的「不安全」是指哪些問題?
笑點一:MD5被破解啦!
2004年的國際密碼學會議(Crypto’2004)王小云證實了MD5能夠被碰撞,至此,MD5再也不安全。沒錯,確實不安全了,可是具體是什麼意思呢?大概多數人根本搞不清楚,也就不知道這個不安全是在哪個場景底下的了。
要說明這個問題,首先要搞懂MD5是一個什麼概念。所謂的MD5其實是一個散列函數,具體說特色以下:
不管多長多隨意的信息,最後都轉換成一個固定長度的散列值;
對於大量不一樣的信息,最後出來的散列值呈平均分佈;
對於特定的一個信息,最後出來的散列值都是相同的。
根據上面的特色,人們一般能夠獲得下面的結論:
不可逆(用一個固定長度的數值,怎麼可能表示任意長度的信息呢);
難碰撞(假如散列值有效範圍是從0到9,那麼平均須要嘗試11次才能找到一個相同的信息。可是,通常來講散列值有效範圍都在2的64次方以上,即0到18,446,744,073,709,551,616之間,甚至更多,你能夠說是一個天文數字);
可表明(既然不可逆,難碰撞,你用散列值是猜不出原來的信息,更不太可能僞造一個信息,其散列值徹底相同。因而你出示一個散列值,就能夠證實你持有某個有效信息,好比密碼)。
好,到這裏你大概能發現,上面結論中的難碰撞貌似不對。沒錯,2004年的破解就是證實了MD5在碰撞上面不可靠,也就是能夠經過某種方式快速的找到具備相同散列值的另外一個信息。比方說:
已知原來的信息是aaaaaaaaaa,散列值是10;
經過某方法,能迅速的找到一個信息aaaXaaaXaa,散列值也是10。
那麼這會形成什麼影響呢?這就須要先說明一下,散列函數均可以用來作什麼:
簽名認證,證實某段信息沒有被修改;
密碼驗證,證實你確實知道某個密碼;
其餘,好比用在哈希表的散列過程等(這一個場景跟安全不要緊,咱就不討論了)。
先說簽名認證。所謂簽名認證就是給出一個信息A,而後運算H(A)=S,同時將A和S記錄起來。當須要校驗信息A有沒有被篡改的時候,只要計算H(A)=S',看S'是否等於S,就知道了。實際上過程比這個複雜,須要運用非對稱加密才能保證安全。但總歸能夠看出來,若是我知道A和S,就能快速推算出一個A'出來,使得H(A')=S,那麼這個簽名認證過程就失效了,或者說就能夠假裝沒有篡改了。
而所謂密碼驗證,就是給定一個密碼A,通過散列運算H(A)=S,此後,每一次用戶登陸的時候輸入A',計算H(A')=S',看看S'是否就是S。若是相等,那就說明用戶知道密碼A,不然就是不知道。在這種應用裏面,若是我知道正確的密碼A,我還須要費半天功夫搞出個A',使得H(A')=S嗎?徹底不必。
換句話說,2004年那個MD5碰撞問題,對於密碼驗證來講,根本就沒多大幹系。那些拿着這個來講MD5在密碼應用上不安全的,壓根就沒搞懂MD5的碰撞不安全是怎麼回事。下次有人再這麼說的時候,你大能夠嘲笑一下對方,哪怕你不知道我上面在說什麼,你只要質問一下「碰撞是什麼意思,請不惜賜教」,多半就啞吧了。
笑點二:已經有很大的MD5密碼(碰撞)庫,有7.8萬億個密碼呢!
另外一個拿來講事的,就是MD5密碼庫如何如何大,好比包含了7.8萬億個密碼。但是……你曉得英文大小寫+數字+2標點共計64種字符,長度是10個字符,總共會有多少個不一樣的密碼嗎?答案是1,152,921,504,606,846,976個,也就是1,152,921.5萬億個。那個7.8萬億個密碼的密碼庫,只佔有這裏面的百萬分之6.7。
可爲何你們的密碼還總是泄露呢?那是由於:
人的記性不好,因此總會選用比較好記的密碼,也就是弱密碼;
人的記性不好,因此總會選擇極有限的幾個密碼用在無窮多的網站上;
沒讀過書的人老是那麼多,因而總用不好勁的方式來對待系統的安所有分,尤爲是密碼部分。
先說弱密碼,由於你總傾向於記生日、人名、單詞,因而你的密碼一般會是:
4位純數字,總計1萬個不一樣的密碼;
6位純數字,總計100萬個不一樣的密碼;
8位之內的小寫字母,並且仍是某種拼音或者單詞,總計估計不超過1000萬個不一樣的密碼;
即使是8位小寫字母加數字,也就是時2.8萬億個不一樣組合。
因此,一個7.8萬億個密碼的密碼庫,足以覆蓋大部分用戶的弱密碼了。但是,問題沒那麼簡單,若是密碼保存和驗證的過程正確,即使有一個7.8萬萬億的密碼庫,黑客也不會搞出你的密碼來——不是不能,而是沒有興趣。
爲何?那就先要搞清楚,密碼是怎麼被破解的。假設明文成爲P,密鑰爲k,加密過程爲E(P,k),獲得的密文是C,而解密過程爲D(C, k)=P。那麼破解的手段大體有以下幾種:
暴力窮舉:最笨最慢的方法,讓P'=0...X,找到E(P', k)=C;
算法分析:研究E(),找到其中的弱點,而後P'=0...Y,找到E(P', k)=C,Y<X;
密文分析:根據C1,C2,...Cn,找到裏面的蛛絲馬跡,直接找到能解密的替代函數D'(),或者直接解出C的部分明文P';
已知明文攻擊:有選擇的給出明文P1,P2,...Pn,讓對方用E(p, k)計算出C1, C2,...Cn,經過分析找到k',使得D(C, k')=P;
生日攻擊:有選擇的給出明文P1,P2,...Pn,而後直接用這些明文嘗試用戶U1, U2,...Un,恰巧某些用戶Ux就是用的其中一個明文。這是後面要講的其中一個重點,所謂加鹽就是要解決相似的問題;
偷聽:監聽鏈路,等用戶U給出P時便可直接得到,或者用戶給出的是E(P,k)=C,則下次也能夠用一樣的協議給出C,假裝用戶U。什麼QQ盜號木馬,就屬於這種形式;
整鍋端:經過後門漏洞等,直接拿到全部數據和程序,而後進行上面的各類分析和攻擊。本次CSDN爲開端的,多數是這種;
間諜(找到人,用各類賄賂,直接拿到E()、D()和k,甚至全部移植的C和P,或者本身拿着這些東西出去賣錢)。
上面的攻擊難度和耗費時間和成本基本上是遞減的,其中整鍋端的這種攻擊,可使得攻擊者能夠選擇更簡單快速的攻擊方式,這取決於密碼保管方採用的什麼保管策略和協議。若是作得好,那麼能作的頂多就是已知明文攻擊,或者針對個別用戶作生日攻擊。若是作得很差,好比說像此次爆發的結果看,就直接拿到明文密碼了。
很顯然,若是用暴力破解,那麼結果就是對每一個用戶嘗試超過1,152,921萬億個不一樣的密碼,這是極其費時而不現實的。因此,大多數狀況下會選擇生日攻擊這種形式,由於大多數人會選擇那些比較好記的密碼,而這些密碼佔整體密碼只是一個極有限的一部分。這就是爲何說7.6萬億個密碼的庫,就能夠攪得大多數網站天翻地覆。那麼這種攻擊具體是如何實施的呢?我來舉一個例子:
好比說你們可能很喜歡使用123456,那麼通過MD5散列以後就能夠獲得一個散列值,好比說是qwerty。因而乎當咱們拿到一個網站的數據庫,發現裏面有爲數很多的用戶,其密碼列保存的是qwerty。這說明幾個問題:
該站點密碼保存的方式很差,極可能是計算C=E(P),保存C;
這些用戶的密碼極可能是相同的。
你只要嘗試一下用qwerty登陸其中一個用戶,發現登陸不了,就能夠得出以下結論:
該站點不是使用明文保存密碼;
該站點使用的是MD5;
該用戶的密碼就是123456。
剩下來要作的事情,就是用那個7.6萬億的密碼庫,逐一比對每一個用戶的密碼列了。
好,第二個MD5不安全的笑點來了:上述破解過程對於絕大多數散列函數來講,基本上都是一個道理。好比說SHA1,用一樣的密碼樣本,也能夠製做出一個7.6萬億的密碼庫,而後接下來的事情就和MD5同樣了。那麼當你們用這個方法都不安全的時候,何來一個說法說MD5就不安全呢?
總結:若是有人跟你說7.6萬億個密碼的密碼庫,你大能夠經過「你知道什麼是生日攻擊或者碰撞攻擊嗎」來嘲笑他,哪怕上面那堆東西你看不懂一個字。
笑點三:MD5加鹽不安全!
還有人會說MD5+salt(就是俗稱的加鹽)不安全,理由是MD5運算很快云云。這樣說的人,確定不知道MD5+salt要避免的問題是什麼,或者說MD5+salt爲何就安全了,甚至大概連MD5+salt的salt是個什麼東西,應該怎麼個加法都不知道。
要搞明白這些個問題,首先要了解兩個最基本的知識:
密碼學的理論安全,是創建在就算你知道了全部其餘的信息包括E()、D()的具體算法,整個加解密的協議,以及保存密文的方法,乃至全部程序源代碼、數據庫,你只要不知道密鑰k是什麼,對於待破解的密文C是不能獲得明文P的,甚至用任意其它明文P'計算出相應的密文C',你也得不到待破解密文C所對應的明文P是什麼;
密碼學的應用安全,是創建在破解所要付出的成本遠超出能獲得的利益上的。
對於保存用戶密碼所用的散列函數來講,是沒有k這回事的。就算有那也是保存在服務端,一鍋端的時候就會拿到。因此要保證理論的安全,就必需要求算法自己不能經過密文C能獲得明文P,這個散列算法自己就能夠作到。另一個要保證的事情,那就是經過各類能夠公開讓你們知道的保存密碼方法,和驗證協議,作到不遭受包括生日攻擊在內的各類攻擊。然而很不幸的是,這種保證明際上是作不到的,或者說沒法在面對這種攻擊的時候,讓針對單個用戶的破解達到近似暴力破解所需時間的程度。關於這個問題舉一個例子:
聽說如今隨便一臺好點的機器,每秒鐘能夠計算700萬個密碼的MD5值。也就是說7.6萬億的密碼庫,須要運算大概1百萬秒,也就是11天半。若是你被FBI,克格勃,或者國家安全局盯上的話,他們確定會用性能強大萬倍以上的機器來對付你。也就是說,這個時間會縮短到大概2分鐘。
因而,實際上密碼保存的着眼點是應用安全。仍是上面的例子,好比說,若是黑客A花5000買了個機器,而這臺機器大概能用2年。若是他用11天半破解了你的帳號,那麼成本大概就等於5000元/2年*11天半=79元。但若是拿到你的帳號密碼以後,裏面能獲取的利益也就5毛,這個黑客A就虧了。虧本生意是不會有人去作的,就算作了,他的損失也比你大。因此應用安全的重點就是提升破解的門檻,手段包括:
增長算法所須要的時間(好比那個宣稱散列一次至少0.3秒的bcrypt);
增長破解全部人的整體時間,等。
前一種方法也不是不行,可是這種方法並不從根本上解決生日攻擊的問題。或者說,產生一個密碼庫的時間從1臺普通機器用11天半,增長到用一個超級計算機集羣用1年,可是隻要有了這個庫以後,對已有的密碼散列值進行生日攻擊只要10秒鐘,那仍是很划算的。由於產生密碼庫的成本是一種沉沒成本,和用戶量有多少徹底沒有關係。好比說,用這個密碼庫去對比一個瑞士銀行帳戶的密碼,只要有幾個沙特王子的密碼在這個密碼庫裏面,你就能夠買下幾百個超級計算機集羣了。
然後者,則是將生成密碼庫的沉沒成本變成邊際成本,也就是說:若是須要爲每個用戶生成一遍密碼庫,那整個破解的成本就會隨着用戶量的提升而急劇增長。好比生成一個用戶的密碼庫須要花11天半的時間,一共有1萬個用戶,所有破解就須要315年的時間。就算生成密碼庫的時間壓縮到10分鐘,所有破解也須要70天的時間。那怎麼作到呢?方法就是加鹽,也就是那個笑點「md5+salt不安全」。
加鹽怎麼加呢?方法以下:
針對每個用戶U,生成一個隨機值Salt,而且在之後永遠保持不變,任意兩個用戶的鹽不能相同。而後當用戶設置密碼的時候,根據明文密碼P,計算MD5(P+Salt)=C。而登陸的時候用戶也給出明文密碼P',服務器拿到以後一樣計算MD5(P'+Salt)=C',看C'是否等於C。咱們來看一下這樣是否就達到目的了:
假設有兩個用戶A和B,密碼都是123456,但鹽分別是aaaa和bbbb,因而MD5(123456+aaaa)=X8jv8o,而MD5(123456+bbbb)=8go489,而再也不是標準的qwerty。這時候:
黑客拿到的只是:用戶A的鹽是aaaa,散列值是X8jv8o。用戶B的鹽是bbbb,散列值是8go489;
首先,標準的密碼庫失效了;
其次,每一個用戶的散列值都不同,你沒法根據相同散列值數量的多少得出哪些是弱密碼;
再次,鹽是aaaa,散列值是X8jv8o,是沒法推導出密碼是123456,仍是abcdef,仍是別的什麼東西,不像在簡單MD5的狀況下,看到qwerty就知道那是123456;
因而,黑客剩下兩個選項:
針對每一個用戶進行暴力破解;或者
針對每個用戶的鹽,好比aaaa,分別根據弱密碼明文庫,計算MD5(弱密碼明文+aaaa)=鹽aaaa對應的散列值,而後再用這個密碼庫去對用戶A進行生日攻擊。對用戶B還得從新根據新的鹽bbbb生成密碼庫……
看,這就是加鹽的做用。
總結:若是你要嘲笑這類人,你能夠質疑他「你知道沉沒成本和邊際成本嗎」,或者「加鹽以後如何進行生日攻擊或者碰撞攻擊」,即使上面寫的東西你都沒看懂。
嗯,其實在這個笑點下面還有一些有意思的分支笑點:
笑點三點一:加固定鹽。
說實話,什麼叫作加固定鹽我一開始沒看懂,直到後來看到說給每一個用戶加隨機鹽我才恍然大悟。那意思是說,給每個用戶都用同樣的鹽,好比用戶A使用鹽aaaa,用戶B也使用aaaa,……用戶ZZZ仍是使用aaaa。你若是看懂了上面我說的內容,大概你就知道鹽是用來防止一個密碼碰撞庫能夠用在全部用戶身上。這種「固定鹽」打一開始就違反了上述原則,根本就不是鹽。因此,在應用密碼學的書裏面壓根就沒有「固定鹽」這樣的說法。
之因此產生固定鹽的想法,大概源於不讓已有的簡單MD5碰撞庫能用在你身上,而且鹽是不會泄露的。鹽這種不是隻有用戶本身才知道的東西,不是密鑰k,若是你的安全性就期望在沒人知道你的「固定鹽」是多少,那就違反了密碼學的準則了,都不須要用腦殼想就知道這是不安全的。並且,人家連你的密碼庫都能拿到,鹽還不是垂手可得的事情麼?
還有說不知道個人算法是什麼,老大,人家能攻破你的系統登進來,把你的整套數據庫拿走,還差程序不成?告訴你,剩下的問題只是你的庫裏面有多少價值而已。若是是一個不要說是銀行庫、淘寶庫,就算是一個社交庫,裏面的價值(好比釣釣魚)都足夠請一個「安全專家」來審閱你的代碼了。不要把這個安全專家想象的過高級,隨便找個有點想象力的技術人員就能夠了,好比這樣的思路:
我已經有你的程序了;
找到生成密碼散列值的入口函數Fuck();
拿一個明文密碼庫,在一個用戶帳號上面不停地改密碼,也就是用每個P不斷地Fuck(P);
好了,密碼碰撞庫就出來了。
固定鹽這種想法還不是最搞笑的,還有下面這一個:
笑點三點二:MD五、SHA一、……這些公開的算法都是不安全的,就算加了鹽也不安全,真正安全的只能是本身寫一個算法,而後再加鹽。
我都懶得說什麼,這種說法除了暴露你的愚昧無知以外,還能有什麼意義呢?這說明你不瞭解:
什麼是MD5;
加鹽是幹什麼的;
密碼學的準則之一是不能依賴於你的算法不被公開;
什麼樣的算法是安全的,怎麼樣算是安全。
有沒有高雅一點的笑點?也有:
笑點三點三:用bcrypt吧,能夠隨意調節運算須要的時間,比MD5慢千萬倍,每秒鐘只能算出3個密碼……
好吧,這也許管用,由於成本確實挺高的。可是:
單純的使用這種算法不加鹽,只不過增長了沉沒成本,邊際成本是不會變的,生日攻擊仍是存在的;
1秒鐘算3個密碼,雖然破解時的成本大大增長了,可是你本身的系統的運行成本也會大大的增長。好比說:原來用MD5時一臺服務器解決用戶登陸問題負載恰好100%,你用這個該死的bcrypt算法就須要該死的上萬臺服務器才能解決問題。
其實這回歸到一個簡單的問題上:你的庫裏面價值幾何?若是你是銀行,興許值得。但對於大部分的站點來講,這麼搞只會過分增長本身的成本,MD5加鹽就已經可讓大部分黑客徹底喪失興趣了。
還有一些相似的說法,也是同樣的。好比說:MD5加鹽多算幾遍。其實這麼作無非就是增長了一些計算成本而已,和bcrypt思路無差別。(固然,也有人覺得這樣多算幾遍由於算法不標準,人家不知道,因而就安全了。請參見笑點三點一。)
其實,只要你加的是真正意義上的鹽——每一個用戶都不相同、隨機的,那其他的手段基本上不是花拳繡腿,就是在表演如何本身砸本身的腳。固然了,不排除有些真的很天才的想法,但大部分人的說法都不在這個範疇內。
總結陳詞
若是你沒讀過某個領域的至少一本書,最好別隨便發言,不然別人一眼就能看出你是個什麼青年;
MD5+salt對於大部分中小網站來講已經足夠安全了;
你實在信不過MD5,那就用點SHA1之流,在密碼驗證這種場景裏面,已經足夠了,除非你是開銀行或者開淘寶的;
身份驗證只是安全的其中一個環節,想一想這些庫都是怎麼被偷出來的,想一想各類QQ木馬……
你在網絡上看到的大部分言論基本上屬於在此領域徹底無知的人所想象出來的錯誤言論,好比說搜索「MD5不安全」,除了極少數個別的抄正規網站的報道外,以及個別真正的安全網站裏面的信息外,幾乎都是各類笑話;
在安全這方面,只要你不是專家,你仍是當他不存在比較好。和食品安全同樣,在網絡安全方面,其實大部分網站這方面作得都很糟糕,你要知道了真實的狀況,恐怕無法用網絡上的東西了。
算法