淺談用戶密碼保護與相關技術

淺談用戶密碼保護與相關技術(上)

一、  全文涉及

上篇:哈希,彩虹表

下篇:加鹽加密,慢哈希,非對稱加密與HTTPS

 

二、  主題引入

2011年12月21日,CSDN後臺數據庫被黑客惡意發佈到互聯網上並提供下載,此數據庫中包含了642萬多個用戶的帳號、密碼等信息,嚴重威脅了相關用戶的信息安全。此次事件之後,人人網、貓撲、嘟嘟牛、178遊戲網等多家網站的部分用戶數據庫也紛紛被傳到網上並提供下載,甚至有媒體曝光國內十幾家大型門戶級網站的數據庫也已經被黑客“拖庫”,因此將2011年末的密碼危機推向了高潮。

令人啼笑皆非的是,csdn作爲號稱最大的中文在線同性程序員交友網站,主要用戶均爲技術人員,而其後臺用戶信息數據庫竟然全部使用明文記錄——這是一種非常低級的行爲。或許單純的csdn賬號泄露不足以引起用戶損失,然而很多用戶通常習慣於多個賬號使用相同的口令密碼。一旦黑客掌握了用戶的社交網絡賬號乃至銀行卡賬號等重要賬號,用戶的隱私及人身財產安全均有可能受到巨大威脅。

       用戶信息數據庫加密保護的重要性如斯,本文將就相關技術進行探討。

 

三、  正文部分

(一) 哈希

哈希函數又名散列函數,是一種不可逆的信息摘要函數

f(x)=y

“不可逆”即無法通過算法由函數值得到輸入值;“信息摘要”是指由輸入值的某些特徵信息值得到最後結果,不同輸入值得到的結果不同。儘管設計的目的是好的,但是由於輸入內容的無限性,而輸出值的有限性,總會出現兩個不同的輸入值出現相同的輸出結果。

注意一點:用於密碼加密的這一類哈希函數是所謂的“加密哈希函數”(cryptographic hash),它們是哈希函數的一個子集,對於安全性的要求比起數據結構中用於分配哈希桶的哈希函數要高出很多。下文中所述的“哈希函數”均指“加密哈希函數”。

一個好的哈希算法,對於不同的輸入值,理應給出很難重複的哈希值。一旦發生這種情況,即出現了所謂的“撞庫”。著名的信息摘要算法“MD5”算法近年來愈發受到詬病,其原因除了本身安全性較低外,還有MD5碼以16進制記錄時僅有的32位長度限制;相比於SHA-256結果足足256位的長度,在電腦的計算力越來越強大的今天,MD5加密已經禁不起黑客們的撞庫破解。

       除此之外,執行效率也是衡量哈希算法的一個重要因素。MD5最初受到廣泛歡迎就是因其極快的執行速度,對於一段字符串僅需毫秒級別的執行時間。因而現在MD5算法雖然在密碼學領域受到排擠,但是仍然被廣泛用於文件校驗等場景。

 

(二) 哈希在用戶信息加密中的應用

哈希因爲不可逆的特性,被廣泛應用於信息加密領域。

一個記錄用戶登錄信息的數據庫,最起碼的要求就是對用戶密碼進行一次加密(然而之前的csdn連這點都沒有做到)。當用戶輸入賬號密碼時,服務器會再次對密碼進行哈希,並將用戶名和哈希值與數據庫中的記錄比對,從而確定用戶是否可以獲得授權。

這樣做的好處是:一旦黑客“拖庫”,即竊取了服務器數據庫中的數據,他仍然無法獲得用戶的明文密碼——他得到的只有哈希值。而完成登陸的正確途徑是輸入可以計算得到相應哈希值的明文密碼,這樣一來黑客就需要找出這樣一個值。

 

(三) 常見的哈希破解方法

對於獲取了哈希結果的黑客來說,下一步要做的就是得到滿足哈希結果的原始口令了。只不過黑客不需要得到與原始值一模一樣的密碼,他的目標只是“碰撞”而已。由於哈希函數有限對應無限的特點,即總有x1≠x2,卻能使hash(x1)=hash(x2)=y。黑客只要能找到與原文密碼生成相同結果的一個字符串就能夠通過服務器的驗證。

而這一過程顯然並不簡單,在擁有彩虹表之前,可以進行的兩種簡單的破解方法是暴力破解法與字典破解法。

 

 

1.   暴力破解

雖然我的算法成績不怎麼樣,但是這不代表我不知道窮舉法是一種糟糕的方法。儘管如此,有時事情就是“知其不可而爲之”。藉助於現代計算機強勁的計算力,黑客將目標定位於全體字符組合的變幻莫測的星辰大海,窮盡天荒地老的時間來追尋那似乎遙不可及的最後的光點。

2.   字典破解

事實證明暴力破解的效率真的不高,於是其進階版本的字典破解出現了。所謂的字典破解,原理就是利用了人類想象力貧瘠和懶得記憶複雜密碼這兩個普遍缺點,將暴力破解的範圍限定在相對小了很多的字符組合中。

事實上,字典破解中收錄了極多的可能出現的密碼組合,並記錄了相應的哈希值——顯然對於不同的加密算法,需要不同版本的字典來記錄。總之,發揮了共享精神的黑客們不斷髮展壯大自己的字典,在簡化破解流程的道路上越走越遠。

只不過美中不足的是,由於字典的體積越來越龐大,查表本身消耗的時間也在快速增長,如何加快查錶速度成爲了技術愛好者們的一大難題。該問題引出了下一個重要概念——彩虹表。

 

(四) 彩虹表

所謂rainbow table,通常被錯誤地描述成一個巨大的原文密碼與其哈希值的對應集合(體積達到可怕的幾百G)。然而事實上彩虹表不是簡單的字典破解的plus版,它所謂的time-memory trade-off,並不是簡單地“以空間換時間”,而是雙向的“交易”,在二者之間達到平衡。

1.   哈希鏈集

在彩虹表的概念之前,就已經出現了針對哈希加密的破解手法——“預計算的哈希鏈集”(Precomputed hash chains)。

對於需要破解的哈希函數H,定義一個定義域和值域與H剛好相反的函數R(reduction function)。很顯然,R不會是H的反函數,但是我們只需要將R的值域限定在H的定義域就好。


定義這樣的一個過程HR:對輸入值首先進行一次H運算,再進行一次    R運算。該過程重複k次後,得到一個哈希鏈:

以上就是進行了2次HR運算的一個哈希鏈。然而,需要儲存的只有頭部的“123”和尾部的“789”而已。數據庫中記錄的就是海量的哈希鏈頭尾形成的元組。

使用時,已經獲取到了哈希結果“def”,嘗試對其進行一次R運算,得到了結果“789”,查表發現“789”存在於表中,這意味着有很大的可能碰撞成功。此時獲知哈希鏈的頭部是“123”,於是使用“123”進行HR過程的哈希鏈計算,很快就發現了“def”對應的原文密碼是“456”。

那麼如果從數據庫中獲取的哈希結果是“abc”呢?事實上,對於一次R計算沒有在表中獲得對應結果的值,就可以開始進行k-1次HR過程,每次完整的HR過程都能得到一個值,用這個值進行查表,一旦得到匹配的哈希鏈尾部結果,就可以使用該鏈的頭部推知原文密碼。選用次數k-1,是因爲更長的HR運算已經超出了一個哈希鏈最大的長度,更多的迭代是沒有意義的。

 

2.   時間與空間的平衡

事實上,儘管哈希鏈集的思想非常不錯,但是它的效率受到一個重大的制約:R函數的選取。R函數首先要能夠成功地把原哈希函數的值域與定義域交換,此外R函數的碰撞也要儘可能小。因爲這兩個要求的存在,想要找到一個優秀的R函數是非常困難的。然而一旦碰撞發生,就會出現下圖所示的情況:


由於哈希鏈出現了部分重複,這兩個哈希鏈能解密的明文數就比理論的2k要低。而且由於表中只記錄了哈希鏈的頭尾,這種重複並不會被輕易發現。隨着表的增大,碰撞頻發,大量的冗餘和浪費就出現了。


2003年,彩虹表算法的提出對這個問題作出了很好的改進:在每一次HR過程中,不再使用相同的R函數,而是分別在k次運算中使用R1,R2,R3,…,Rk共k種不同的R函數。這種情況下即使發生碰撞,也通常是如下情況:

由於不同的R函數,使得碰撞帶來的冗餘大大減少。只不過這樣產生的哈希鏈在用於解密時需要的步驟稍微複雜一些。


 

參考資料:

[1] 張耀輝.CSDN“拖庫”事件後對密碼保護的反思

[2] 維基百科. 散列函數

https://zh.wikipedia.org/wiki/%E6%95%A3%E5%88%97%E5%87%BD%E6%95%B8

[3] Wikipedia.MD5

       https://en.wikipedia.org/wiki/MD5

[4] 撞庫 拖庫與洗庫

http://blog.csdn.net/daliaojie/article/details/42171177

[5] What is the differencebetween a Hash Function and a Cryptographic Hash Function?——CodesInChaos’s answer

https://security.stackexchange.com/questions/11839/what-is-the-difference-between-a-hash-function-and-a-cryptographic-hash-function

[6] 什麼是彩虹表?——Smallay的回答

https://www.zhihu.com/question/19790488


淺談用戶密碼保護與相關技術(下)


一、  全文涉及

上篇:哈希,彩虹表

下篇:加鹽加密,慢哈希,非對稱加密與HTTPS

 

二、  正文部分(接上篇)

(一) 加鹽加密

在上一篇中介紹了常用的加密手段——哈希,以及黑客們常用的哈希解密方法——暴力破解、字典破解和彩虹表。其中彩虹表以高效快速著稱,是哈希解密的不二選擇。

只不過魔高一尺,道高一丈,彩虹表也不是戰無不勝的。一個強有力的對抗方案就是使用加鹽加密。

加鹽加密是指在加密密碼時,不只是對密碼進行hash,而是對密碼進行添油加醋,放點鹽(salt)再加密。比如原本的密碼是“123456”,不加鹽的加密方法是hash(“123456”),很容易被彩虹表攻破;而如果使用字符串拼接,將“鹽”加到原文密碼的後面,可能效果就是這樣的:hash(“123456”+”abcdef”)。

服務器驗證時,也是先將原文密碼加鹽再進行哈希,此時黑客使用彩虹表破解出來的結果便無法通過驗證了。假設黑客恰好得出了“正確的”原文密碼,即“123456abcdef”,但是服務器真正驗證的是hash(“123456abcdef”+”abcdef”),黑客提交的密碼依然是無效的。

隨之而來的問題就是鹽的選取了。

每次哈希加密都使用相同的鹽值是很容易犯的一個錯誤,這個鹽值要麼被硬編碼到程序裏,要麼只在第一次使用時隨機獲得。這樣加鹽的方式是做無用功,因爲兩個相同的密碼依然會得到相同的哈希值。攻擊者仍然可以使用反向查表法對每個值進行字典攻擊,只需要把鹽值應用到每個猜測的密碼上再進行哈希即可。如果鹽值被硬編碼到某個流行的軟件裏,可以專門爲這個軟件製作查詢表和彩虹表,那麼破解它生成的哈希值就變得很簡單了。

用戶創建賬戶或每次修改密碼時,都應該重新生成新的鹽值進行加密。

如果鹽值太短,攻擊者可以構造一個查詢表包含所有可能的鹽值。以只有3個ASCII字符的鹽值爲例,一共有95x95x95=857,375種可能。這看起來很多,但是如果對於每個鹽值查詢表只包含1MB最常見的密碼,那麼總共只需要837GB的儲存空間。一個普通的移動硬盤就能解決問題。

爲了使攻擊者無法構造包含所有可能鹽值的查詢表,鹽值必須足夠長。一個好的做法是使用和哈希函數輸出的字符串等長的鹽值,比如SHA256算法的輸出是256位(32bytes),那麼鹽值也至少應該是32個隨機字節。

爲了讓黑客在破解密碼的時候受到更大的阻力,技術人員可以說是八仙過海各顯神通。爲了提高密碼破解的難度,網絡上流行着各種組合哈希加密的方法——比如說md5(sha256(password)+md5(salt))之類。然而對於這些獨創方法,各方褒貶不一。因此接下來將介紹另外一種思路:使用一種時間複雜度更高的加密方法。

 

(二) 慢哈希

天下武功,唯快不破。然而在密碼學中則不同。算法越快,越容易被破。

加鹽加密的方法並不是萬無一失的,一旦黑客擁有了龐大的計算能力,他完全可以耐着性子自己製作字典或彩虹表,這樣一來安全系統還是難逃毒手;另一種特殊情況是,一旦黑客是有目標的,只需要破解某個用戶的賬戶密碼,那麼他的成功概率就更是大幅提升了。

慢哈希的思想就是把哈希函數變得很慢——準確地說是消耗更多的計算資源,於是即使有着超高性能的GPU或定製硬件,字典攻擊和暴力攻擊也會慢得讓攻擊者無法接受。最終的目標是把哈希函數的速度降到足以讓攻擊者望而卻步。

例如使用快男md5進行加密,每次哈希計算的時間可能只需要1微秒,黑客每秒可以猜詞1000000個;如果將哈希一次的時間提高到10毫秒,黑客每秒就只能猜詞100個,破解速度慢了一萬倍。

這種慢哈希的實現依賴一種叫做密鑰【yuè】擴展的技術。密鑰擴展的實現是依靠一種CPU密集型哈希函數。不要嘗試自己設計簡單的迭代哈希加密,如果迭代不夠多,是可以被高效的硬件快速並行計算出來的,就和普通哈希一樣。應該使用標準的成熟算法,比如PBKDF2或者bcrypt。

這類算法使用一個安全因子或迭代次數作爲參數,這個值決定了哈希函數會有多慢。將安全因子調的越高黑客破解的難度也越高。

然而事情沒有這麼簡單,使用了慢哈希對服務端的計算能力也提出了要求。併發登錄過多或者出現惡意用戶發起DoS(拒接服務攻擊)時,系統資源可能出現被耗盡的風險,所以安全因子也不能一味設置得過高。

另外一種稍顯巧妙的解決方案是:利用客戶端的計算力。如果在客戶端利用用戶自己的設備完成初步加密,再對中間結果在服務端進行相對簡單的加鹽加密,兩全其美,豈不美哉?

事實上,這種解決方案並不安全,尤其是對於網頁源碼公開的web應用來說。一旦黑客拿到數據庫,他並沒有必要非得獲取用戶的原文密碼才行,直接使用中間值繞過前端慢加密直接調服務器的登錄接口,是更加方便快捷的選擇!所以服務端的再次加密是絕對必要的。這樣看來,這種所謂“巧妙”的方案的的風險也相對較高,對於使用信息傳遞沒有保障的HTTP協議的網站來說更是如此。

 

然而,以上所有的加密方法都不是萬全的,因爲黑客有可能在網絡的任何位置攔截數據包,並獲取到密碼的明文或加密後的中間值,抑或僞裝成用戶騙取服務器的信任。要避免這種情況出現,最好的方式就是使用引入了非對稱加密的HTTPS協議。

 

(三) 非對稱加密與HTTPS

1.    非對稱加密

非對稱加密是相對於對稱加密而言的。

傳統的對稱加密方式,必須要求收發信息的雙方使用同樣的密鑰進行加密和解密。但是當數據在互聯網上傳遞時,無法保證兩方擁有這種配合默契的密鑰。因此密鑰不可避免地要被隨着數據一同發送——在極易被截獲數據包的網絡傳輸中,這種行爲是沒有太大意義的。而即使對密鑰進一步加密,黑客要獲得加密算法也不是非常困難的事情。

非對稱加密正是爲了解決這種問題而出現的。

簡單概括非對稱加密的思想:這種加密方式使用公鑰和私鑰進行,但是公鑰是用於完成加密的,並不能對已加密的信息解密,解密工作只能由相對應的私鑰進行;反之,私鑰加密的內容只能使用公鑰進行解密。如果我們希望和別人通信,我們就將自己的公匙給他,他使用我們的公匙加密信息產生密文,而我們使用自己妥善保管的私匙對密文進行解密。由於上面提到的公匙和私匙產生密文的唯一對應的特性,任何使用你的公匙加密的信息,只有你私匙纔可以解密。這樣通過將加密和解密的密匙進行分離,我們不必將解密密匙告訴別人,從而提高加密的安全性。

 

2.    HTTPS

先介紹“數字簽名”的概念,每次對要發送的數據進行摘要(使用某種哈希),將摘要用私鑰加密後附加在最後,這樣對方就可以使用公鑰驗證信息的準確性。

但是考慮這種情況:黑客想欺騙用戶,他偷偷用自己的公鑰進行了替換。此時,用戶實際擁有的是黑客的公鑰,但是還以爲這是服務器的公鑰。因此,黑客就可以冒充服務器,用自己的私鑰做成"數字簽名",發送消息用戶,讓用戶用假的服務器公鑰進行解密。

爲了確認公鑰真正的所有者,需要藉助第三方的幫助。服務器被要求在CA(certificate authority,證書中心)做公鑰認證。CA利用自己的私鑰,將請求認證的服務方的公鑰和相關信息加密,生成“數字證書”。這樣,服務方就可以在自己的信息後附加數字證書即可。獲取了證書的用戶,會用從CA得到公鑰進行證書的解密驗證,最終確定發送消息者的真實身份。

HTTPS協議正是使用了以上機制的安全版的HTTP。完整的過程如下:

首先,客戶端向服務器發出加密請求。

服務器用自己的私鑰加密網頁以後,連同本身的數字證書,一起發送給客戶端。

客戶端(瀏覽器)的"證書管理器",有"受信任的根證書頒發機構"列表。客戶端會根據這張列表,查看解開數字證書的公鑰是否在列表之內。

如果數字證書記載的網址,與你正在瀏覽的網址不一致,就說明這張證書可能被冒用,瀏覽器會發出警告。

如果這張數字證書不是由受信任的機構頒發的,瀏覽器會發出另一種警告。

如果數字證書是可靠的,客戶端就可以使用證書中的服務器公鑰,對信息進行加密,然後與服務器交換加密信息。

 

有了如此完備的安全機制的HTTPS,纔是網站信息安全的理想保障。當然HTTPS也不是萬無一失的,出於服務方和用戶兩方的安全考慮,服務方設計出好的加密措施、完備管理機制,用戶增強自己的網絡安全意識都是必不可少的。


 

參考資料:

 [1] CoderZh Blog.設計安全的賬號系統的正確姿勢

https://blog.coderzh.com/2016/01/03/security-design/

[2] Defuse Security.SaltedPassword Hashing - Doing it Right

https://crackstation.net/hashing-security.htm

[3] EtherDrea.對抗明文口令泄露 —— Web 前端慢 Hash

       https://www.cnblogs.com/index-html/archive/2015/11/27/4999897.html

[4] 百度百科.對稱加密

http://baike.baidu.com/item/%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86

[5] mconintet.非對稱加密和數字證書

       http://www.jianshu.com/p/da70e98b71f7

[6] 阮一峯的網絡日誌.數字簽名是什麼?

       http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

[7] 吾道永昌.HTTP與HTTPS的區別

       http://www.cnblogs.com/wudaoyongchang/p/6253451.html

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章