如何安全地存儲密碼




無論是開發App還是網站,只要有用戶登錄環節,就會牽涉到如何存儲用戶的密碼的問題。如果采用的存儲密碼的技術不夠安全,一旦黑客闖入存儲密碼的數據庫,他就能獲取用戶的密碼從而可能給用戶帶來重大損失。這種情形任何公司都不希望發生在自己身上,因此選擇安全地存儲密碼的策略顯得十分必要。

不一定非要自己存儲用戶的密碼

最簡單的存儲密碼的方式就是自己並不存儲,而是委托給信任的第三方存儲。這就是OpenID技術,它的理念是用第三方來完成用戶驗證的操作。目前國外的網站如谷歌、雅虎等,國內的如騰訊等都已經提供OpenID的服務。如果我們開發一個網站並選擇谷歌的OpenID服務,那么用戶就可以用Gmail的賬號和密碼登錄,接下來用戶認證的事情將由谷歌完成。

采用OpenID技術無論是對網站的開發者還是用戶,就具備明顯的優點。由於用戶的登錄認證是由第三方的OpenID服務提供商完成的,我們自己沒有必要存儲用戶名和密碼,也就沒有必要考慮存儲密碼的安全性問題,從而減少開發的成本。同時,用戶不用在我們的網站上注冊新的用戶名和密碼。這樣既免去了用戶在注冊用戶名和密碼時填寫資料的麻煩,也減去了用戶需要記住一對新的用戶名和密碼的負擔。

千萬不要用明文存儲密碼

有很多公司由於種種原因不願意把自己客戶的登錄信息保存在其他公司,於是不得不自己存儲用戶的密碼。既然決定自己存儲,就要考慮存儲的安全性。密碼存儲的最低要求是不能用明文(沒有經過加密)存儲密碼。如果用明文存儲密碼,一旦數據庫泄露出去,所有用戶的密碼就毫無保留地暴露在黑客的面前,這可能給用戶以及公司帶來巨大的損失。

雖然不能用明文存儲密碼的道理顯而易見,但實際上仍然有不少公司在采用這種極度不安全的方式。這一點從時不時爆出的各種網站密碼泄露事件可以看出。對那些仍然在用明文存儲密碼的公司,我們只能奉勸他們盡早用哈希算法給密碼加密之后再存儲,別等到密碼泄露之后造成重大損失才幡然大悟。

用哈希算法加密密碼

常用的給密碼加密的算法是幾種單向的哈希算法。所謂的單向的算法是指我們只能從明文生成一個對應的哈希值,卻不能反過來根據哈希值得到對應的明文。經常被大家用來加密的算法有MD5SHA系列(如SHA1SHA256SHA384SHA512等)。值得注意的是,MD5算法已經被中國數學家王小雲破解,因此這種算法已經不建議在產品中使用。

雖然用哈希算法能提高密碼存儲的安全性,但還是不夠安全。通常黑客在侵入保存密碼的數據庫之后,他會隨機猜測一個密碼,用哈希算法生成一個哈希值。如果該哈希值在數據庫中存在,那么他就猜對了一個用戶的密碼。如果沒有猜中也沒有關系,他可以再次隨機猜測下一個密碼進行嘗試。事實上黑客為了提高破解密碼的效率,他們會事先計算大量密碼對應的各種哈希算法的哈希值,並把密碼及對應的哈希值存入一個表格中(這種表格通常被稱為彩虹表)。在破解密碼時只需要到事先准備的彩虹表里匹配即可。因此現在黑客們破解僅僅只用哈希算法加密過的密碼事實上已是不費吹灰之力。

加鹽提高安全性

為了應對黑客們用彩虹表破解密碼,我們可以先往明文密碼加鹽,然后再對加鹽之后的密碼用哈希算法加密。所謂的鹽是一個隨機的字符串,往明文密碼里加鹽就是把明文密碼和一個隨機的字符串拼接在一起。由於鹽在密碼校驗的時候還要用到,因此通常鹽和密碼的哈希值是存儲在一起的。

采用加鹽的哈希算法對密碼加密,有一點值得注意。我們要確保要往每個密碼里添加隨機的唯一的鹽,而不是讓所有密碼共享一樣的鹽。如果所有密碼共享統一的鹽,當黑客猜出了這個鹽之后,他就可以針對這個鹽生成一個彩虹表,再將我們加鹽之后的哈希值到他的新彩虹表里去匹配就可以破解密碼了。

雖然加鹽的算法能有效應對彩虹表的破解法,但它的安全級別並不高,這是由於哈希算法的特性造成的。哈希算法最初是用來確保網絡傳輸數據時的數據完整性。當我們通過網絡傳輸一個數據包時,我們在發送時會在數據包的末尾附上這個數據包對應的哈希值。在接收數據時,我們再次根據接收到的數據包用同樣的算法生成一個哈希值。如果這個哈希值和從網絡上接收到的哈希值一樣,那就證明了數據在傳輸時沒有出現問題。為了減少網絡傳輸的延時,我們希望哈希算法盡量的快,盡可能地減少數據校驗的時間。因此在設計哈希算法的時候,快速高效是一個非常重要的指標。目前在普通配置的電腦上,主流的哈希算法的耗時在微秒的級別,這意味着我們可以在一秒之類計算哈希值近百萬次。

快速高效的哈希算法給加密算法帶來了不少的挑戰,因為安全的加密算法應該是黑客極難破解的算法,而計算哈希值的耗時非常短,黑客們就可以用暴力法去破解加鹽之后的用哈希算法加密的密碼。前面提到,鹽通常和哈希值存儲在一起。於是黑客針對每一個鹽可以采用兩種簡單的暴力法破解密碼。

一是采用窮舉法。黑客生成一個密碼,和鹽拼接在一起再計算哈希值。如果哈希值和數據庫中的哈希值一致,那么這個密碼就被破解。如果不一致,在進行下一次嘗試。這種方法對低級別的密碼非常有效。比如6位全是數字的密碼總共只有一百萬中可能。這意味着任何6位的純數字密碼即使加鹽之后也能在數秒之內破解。雖然用暴力法破解高級別的密碼(比如同時包含數字、大小寫字母和特殊符號的密碼)目前還需要大量的時間,但計算能力遵循着摩爾定律持續地提高,今天看來非常耗時的操作在今后可能非常快速地完成。另外,近年來雲計算的快速發展,也使得黑客們能夠用非常便宜的價格租到大量的計算機以方便他們並行地破解密碼,從而黑客們低成本並且高效地破解高級別密碼成為了可能。

二是黑客們從歷次密碼泄露事件中收集了大量的常用密碼。針對每一個鹽,黑客可以循環地從這些重用密碼里挑選一個,加鹽再計算哈希值。因此這些常用的密碼即使加鹽也很容易破解。

BCrypt或者PBKDF2增加破解的難度

為了應對暴力破解法,我們需要非常耗時的而不是非常高效的哈希算法。BCrypt算法應運而生。我們可以用BCrypt算法加鹽之后給密碼生成一個哈希值。Bcrypt最大的特點是我們可以通過參數設置重復計算的次數。顯而易見重復計算的次數越多耗時越長。如果計算一個哈希值需要耗時1秒甚至更多,那么黑客們采用暴利法破解密碼將不再可能。以前面提到的6位純數字密碼為例,破解一個密碼需要耗時11.5天,更不要說高安全級別的密碼了。

目前已有開源項目(http://bcrypt.sourceforge.net/)實現了BCrypt算法並被業界廣泛采用。如果你是一個.NET程序員,你可能會發現目前的.NETFramework中還沒有包含BCrypt的實現。此時有兩個選擇。一是已經有一些開源項目用C#實現了BCrypt算法,我們可以直接使用。如果對這些實現的安全性存在擔憂,我們也可以選擇和BCrypt類似的PBKDF2PBKDF2同樣也可以通過參數設定重復計算的次數從而延長計算時間。在.NETFramework中,類型Rfc2898DeriveBytes實現了PBKDF2的功能。

小結

安全地存儲密碼不是一件容易的事情。雖然目前有很多公司采用加鹽的哈希算法應對彩虹表破解法,但這種方法並不是足夠安全的。由於哈希算法非常高效,計算哈希值耗時在微秒級別,因此黑客可以通過暴力法破解密碼。一個推薦的辦法用BCrypt或者PBKDF2延長計算哈希值的時間,從而提高破解密碼的難度。另外,並不是每個公司、項目都需要自己存儲密碼。我們的另一個選擇是用OpenID把用戶校驗工作委托給可以信賴的第三方公司。

原文地址:https://blog.csdn.net/cadcisdhht/article/details/19282407


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM