不管是開發App仍是網站,只要有用戶登陸環節,就會牽涉到如何存儲用戶的密碼的問題。若是採用的存儲密碼的技術不夠安全,一旦黑客闖入存儲密碼的數據庫,他就能獲取用戶的密碼從而可能給用戶帶來重大損失。這種情形任何公司都不但願發生在本身身上,所以選擇安全地存儲密碼的策略顯得十分必要。html
最簡單的存儲密碼的方式就是本身並不存儲,而是委託給信任的第三方存儲。這就是OpenID技術,它的理念是用第三方來完成用戶驗證的操做。目前國外的網站如谷歌、雅虎等,國內的如騰訊等都已經提供OpenID的服務。若是咱們開發一個網站並選擇谷歌的OpenID服務,那麼用戶就能夠用Gmail的帳號和密碼登陸,接下來用戶認證的事情將由谷歌完成。程序員
採用OpenID技術不管是對網站的開發者仍是用戶,就具有明顯的優勢。因爲用戶的登陸認證是由第三方的OpenID服務提供商完成的,咱們本身沒有必要存儲用戶名和密碼,也就沒有必要考慮存儲密碼的安全性問題,從而減小開發的成本。同時,用戶不用在咱們的網站上註冊新的用戶名和密碼。這樣既免去了用戶在註冊用戶名和密碼時填寫資料的麻煩,也減去了用戶須要記住一對新的用戶名和密碼的負擔。算法
有不少公司因爲種種緣由不肯意把本身客戶的登陸信息保存在其餘公司,因而不得不本身存儲用戶的密碼。既然決定本身存儲,就要考慮存儲的安全性。密碼存儲的最低要求是不能用明文(沒有通過加密)存儲密碼。若是用明文存儲密碼,一旦數據庫泄露出去,全部用戶的密碼就毫無保留地暴露在黑客的面前,這可能給用戶以及公司帶來巨大的損失。數據庫
雖然不能用明文存儲密碼的道理顯而易見,但實際上仍然有很多公司在採用這種極度不安全的方式。這一點從時不時爆出的各類網站密碼泄露事件能夠看出。對那些仍然在用明文存儲密碼的公司,咱們只能奉勸他們儘早用哈希算法給密碼加密以後再存儲,別等到密碼泄露以後形成重大損失才幡然大悟。安全
經常使用的給密碼加密的算法是幾種單向的哈希算法。所謂的單向的算法是指咱們只能從明文生成一個對應的哈希值,卻不能反過來根據哈希值獲得對應的明文。常常被你們用來加密的算法有MD5和SHA系列(如SHA1、SHA256、SHA384、SHA512等)。值得注意的是,MD5算法已經被中國數學家王小云破解,所以這種算法已經不建議在產品中使用。網絡
雖然用哈希算法能提升密碼存儲的安全性,但仍是不夠安全。一般黑客在侵入保存密碼的數據庫以後,他會隨機猜想一個密碼,用哈希算法生成一個哈希值。若是該哈希值在數據庫中存在,那麼他就猜對了一個用戶的密碼。若是沒有猜中也沒有關係,他能夠再次隨機猜想下一個密碼進行嘗試。事實上黑客爲了提升破解密碼的效率,他們會事先計算大量密碼對應的各類哈希算法的哈希值,並把密碼及對應的哈希值存入一個表格中(這種表格一般被稱爲彩虹表)。在破解密碼時只須要到事先準備的彩虹表裏匹配便可。所以如今黑客們破解僅僅只用哈希算法加密過的密碼事實上已經是不費吹灰之力。網站
爲了應對黑客們用彩虹表破解密碼,咱們能夠先往明文密碼加鹽,而後再對加鹽以後的密碼用哈希算法加密。所謂的鹽是一個隨機的字符串,往明文密碼里加鹽就是把明文密碼和一個隨機的字符串拼接在一塊兒。因爲鹽在密碼校驗的時候還要用到,所以一般鹽和密碼的哈希值是存儲在一塊兒的。雲計算
採用加鹽的哈希算法對密碼加密,有一點值得注意。咱們要確保要往每一個密碼裏添加隨機的惟一的鹽,而不是讓全部密碼共享同樣的鹽。若是全部密碼共享統一的鹽,當黑客猜出了這個鹽以後,他就能夠針對這個鹽生成一個彩虹表,再將咱們加鹽以後的哈希值到他的新彩虹表裏去匹配就能夠破解密碼了。加密
雖然加鹽的算法能有效應對彩虹表的破解法,但它的安全級別並不高,這是因爲哈希算法的特性形成的。哈希算法最初是用來確保網絡傳輸數據時的數據完整性。當咱們經過網絡傳輸一個數據包時,咱們在發送時會在數據包的末尾附上這個數據包對應的哈希值。在接收數據時,咱們再次根據接收到的數據包用一樣的算法生成一個哈希值。若是這個哈希值和從網絡上接收到的哈希值同樣,那就證實了數據在傳輸時沒有出現問題。爲了減小網絡傳輸的延時,咱們但願哈希算法儘可能的快,儘量地減小數據校驗的時間。所以在設計哈希算法的時候,快速高效是一個很是重要的指標。目前在普通配置的電腦上,主流的哈希算法的耗時在微秒的級別,這意味着咱們能夠在一秒之類計算哈希值近百萬次。spa
快速高效的哈希算法給加密算法帶來了很多的挑戰,由於安全的加密算法應該是黑客極難破解的算法,而計算哈希值的耗時很是短,黑客們就能夠用暴力法去破解加鹽以後的用哈希算法加密的密碼。前面提到,鹽一般和哈希值存儲在一塊兒。因而黑客針對每個鹽能夠採用兩種簡單的暴力法破解密碼。
一是採用窮舉法。黑客生成一個密碼,和鹽拼接在一塊兒再計算哈希值。若是哈希值和數據庫中的哈希值一致,那麼這個密碼就被破解。若是不一致,在進行下一次嘗試。這種方法對低級別的密碼很是有效。好比6位全是數字的密碼總共只有一百萬中可能。這意味着任何6位的純數字密碼即便加鹽以後也能在數秒以內破解。雖然用暴力法破解高級別的密碼(好比同時包含數字、大小寫字母和特殊符號的密碼)目前還須要大量的時間,但計算能力遵循着摩爾定律持續地提升,今天看來很是耗時的操做在從此可能很是快速地完成。另外,近年來雲計算的快速發展,也使得黑客們可以用很是便宜的價格租到大量的計算機以方便他們並行地破解密碼,從而黑客們低成本而且高效地破解高級別密碼成爲了可能。
二是黑客們從歷次密碼泄露事件中收集了大量的經常使用密碼。針對每個鹽,黑客能夠循環地從這些重用密碼裏挑選一個,加鹽再計算哈希值。所以這些經常使用的密碼即便加鹽也很容易破解。
爲了應對暴力破解法,咱們須要很是耗時的而不是很是高效的哈希算法。BCrypt算法應運而生。咱們能夠用BCrypt算法加鹽以後給密碼生成一個哈希值。Bcrypt最大的特色是咱們能夠經過參數設置重複計算的次數。顯而易見重複計算的次數越多耗時越長。若是計算一個哈希值須要耗時1秒甚至更多,那麼黑客們採用暴利法破解密碼將再也不可能。之前面提到的6位純數字密碼爲例,破解一個密碼須要耗時11.5天,更不要說高安全級別的密碼了。
目前已有開源項目(http://bcrypt.sourceforge.net/)實現了BCrypt算法並被業界普遍採用。若是你是一個.NET程序員,你可能會發現目前的.NETFramework中尚未包含BCrypt的實現。此時有兩個選擇。一是已經有一些開源項目用C#實現了BCrypt算法,咱們能夠直接使用。若是對這些實現的安全性存在擔心,咱們也能夠選擇和BCrypt相似的PBKDF2。PBKDF2一樣也能夠經過參數設定重複計算的次數從而延長計算時間。在.NETFramework中,類型Rfc2898DeriveBytes實現了PBKDF2的功能。
安全地存儲密碼不是一件容易的事情。雖然目前有不少公司採用加鹽的哈希算法應對彩虹表破解法,但這種方法並非足夠安全的。因爲哈希算法很是高效,計算哈希值耗時在微秒級別,所以黑客能夠經過暴力法破解密碼。一個推薦的辦法用BCrypt或者PBKDF2延長計算哈希值的時間,從而提升破解密碼的難度。另外,並非每一個公司、項目都須要本身存儲密碼。咱們的另外一個選擇是用OpenID把用戶校驗工做委託給能夠信賴的第三方公司。
原文地址:https://blog.csdn.net/cadcisdhht/article/details/19282407