近期,Github被爆出,在內部日誌中記錄了明文密碼。html
雖然聽說影響面很小,可是網絡和數據安全問題又一次被放到檯面上。大多數用戶的經常使用密碼就那麼幾個,一旦被黑客拿到,去其餘網站「撞庫」,可能會形成用戶的財產損失。git
本篇文章主要介紹如何加密傳輸和存儲用戶密碼,並講解相關原理。github
加密主要有兩種方式:對稱加密和非對稱加密。算法
對稱加密:在加密和解密時使用的是同一個祕鑰。數據庫
對稱加密的模式是:安全
客戶端和服務端進行通訊,採用對稱加密,若是隻使用一個祕鑰,很容易破解;若是每次用不一樣的祕鑰,海量祕鑰的管理和傳輸成本又會比較高。網絡
非對稱加密:須要兩個密鑰來進行加密和解密,這兩個祕鑰是公開密鑰(public key,簡稱公鑰)和私有密鑰(private key,簡稱私鑰)。函數
非對稱加密的模式則是:網站
即便黑客拿到了公鑰,沒有私鑰也是沒有辦法解密,不考慮彩虹表的狀況,徹底能夠長期使用一對祕鑰。加密
最經典的非對稱加密算法是RSA算法。
RSA公鑰加密算法是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一塊兒提出的。公鑰私鑰成對出現,用其中一個加密只能用另外一個解密,一般用公鑰加密私鑰解密。
爲何RSA可以作到非對稱加密呢?
互質關係:若是兩個正整數,除了1之外,沒有其餘公因子,咱們就稱這兩個數是互質關係
簡單來講,RSA利用的原理是,若是兩個互質關係的正整數的乘積足夠大,是極難進行因式分解的(目前被破解的最長RSA密鑰是768個二進制位,而正常使用的至少是1024位的密鑰)。
經過必定的運算,把某計算結果和乘積做爲公鑰,另外一個計算結果和乘積做爲私鑰,便可以實現,利用公鑰進行加密,並利用私鑰進行解密。具體的數學公式推導和證實能夠參考RSA算法原理。
傳輸層面的加密解密原理講的差很少了,咱們來看看github是如何傳輸帳號密碼的。
抓包看一下登陸請求的request,赫然發現,密碼是經過明文傳輸的……
那麼,這種傳輸方式安全嘛?還能夠,由於使用了https,但還不夠安全。
常規的http請求,全部信息明文傳播,只要中間人在鏈路中的任意階段進行劫持,就會帶來三大風險:
怎麼解決這些問題?用https。
https 能夠認爲是 http + TLS TLS 是傳輸層加密協議,它的前身是 SSL 協議,若是沒有特別說明,SSL 和 TLS 說的都是同一個協議。
SSL/TLS協議是爲了解決http的三大風險而設計的,但願達到:
說了這麼多,https作了什麼?結合如下流程圖,講解一次https請求都發生了什麼:
客戶端發起https請求
服務端的配置
通常須要向權威機構申請一個證書(也能夠本身製做,這個會在以後的中間人攻擊中講到,區別就是本身頒發的證書須要客戶端驗證經過,才能夠繼續訪問,而使用受信任的公司申請的證書則不會提示),證書會生成RSA加密使用的一對公鑰A和私鑰B。
這個證書主要內容是公鑰A,也包含了其餘信息,如證書的頒發機構,過時時間等等。
由客戶端的TLS來完成的,主要是驗證公鑰A是否有效,好比頒發機構,過時時間等等,若是發現異常,則會彈出一個警告框,提示證書存在問題。若是證書沒有問題,那麼就生成一個隨機值。以後就進入了不對稱加密的過程,首先用證書對該隨機值進行加密。
這部分傳送的是用證書加密後的隨機值,目的就是讓服務端獲得這個隨機值,後續全部的數據均可以用這個隨機值(即私鑰C),進行對稱加密和解密。
服務端用私鑰B解密後,獲得了客戶端傳過來的私鑰C,到此RSA非對稱加密的過程結束了。
服務端用私鑰C加密信息。
客戶端用以前生成的私鑰C解密服務端傳過來的信息,因而獲取瞭解密後的內容。整個過程第三方即便監聽到了數據,也一籌莫展。
上面的過程,看起來彷佛無懈可擊?並非,由於「人」纔是安全系統中最脆弱的環節。
https信息的安全,徹底創建在證書可信的基礎上,若是中間人僞造證書怎麼辦?
黑客本身僞造的證書須要客戶端驗證經過,才能夠繼續訪問,只要客戶端驗證經過,那麼公鑰A,私鑰B和私鑰C對黑客來講都是透明的,也有沒有數據安全可言了,因此黑客只要誘導用戶安裝本身僞造的證書便可,例如使用各類釣魚的不可描述網站。
因此即便使用https傳輸明文密碼,也不是絕對安全的。那怎麼樣才能保證密碼安全呢?
抓包看一下百度的登陸請求發現,密碼是加密過的:
怎麼加密的?咱們發現,有這麼一個關鍵請求:
意味着,密碼使用RSA進行加密和解密處理的。那麼流程是什麼樣的呢?
查了一下github中,關鍵詞RSA,star數最多的JavaScript庫jsencrypt,驚喜的發現,百度登陸的加密方式和使用的函數名都和這個庫一致,那咱們是否是能夠大膽假設百度整套登陸請求時的流程和這個開源庫基本一致呢,那jsencrypt的流程又是什麼樣的呢:
到這裏,加密傳輸的過程已經完結了,如今服務端已經收到了用戶真實的密碼(解密後的),那怎麼存儲這個密碼呢?
若是用明文存儲密碼(無論是存在數據庫仍是日誌中),一旦數據泄露,全部用戶的密碼就毫無保留地暴露在黑客的面前,開頭提到的風險就可能發生,那咱們費半天勁加密傳輸密碼也失去了意義。
單向加密算法:只能從明文生成一個對應的哈希值,不能反過來根據哈希值獲得對應的明文。
經常使用的給密碼加密的算法是幾種單向的哈希算法。
常常被你們用來加密的算法有MD5和SHA系列(如SHA一、SHA25六、SHA38四、SHA512等)。
雖然用哈希算法能提升密碼存儲的安全性,但仍是不夠安全。
一般黑客在侵入保存密碼的數據庫以後,他會隨機猜想一個密碼,生成一個哈希值。若是該哈希值在數據庫中存在,那麼他就猜對了一個用戶的密碼。若是沒有猜中也沒有關係,他能夠再次隨機猜想下一個密碼進行嘗試。
事實上黑客爲了提升破解密碼的效率,他們會事先計算大量密碼對應的各類哈希算法的哈希值,並把密碼及對應的哈希值存入一個表格中(這種表格一般被稱爲彩虹表),在破解密碼時只須要到事先準備的彩虹表裏匹配便可。所以如今黑客們破解僅僅只用哈希算法加密過的密碼事實上已經是不費吹灰之力。
鹽:一個隨機的字符串,往明文密碼里加鹽就是把明文密碼和一個隨機的字符串拼接在一塊兒。
爲了應對黑客們用彩虹表破解密碼,咱們能夠先往明文密碼加鹽,而後再對加鹽以後的密碼用哈希算法加密。因爲鹽在密碼校驗的時候還要用到,所以一般鹽和密碼的哈希值是存儲在一塊兒的。
採用加鹽的哈希算法對密碼加密,要確保要往每一個密碼裏添加隨機的惟一的鹽,而不是讓全部密碼共享同樣的鹽。
雖然加鹽的算法能有效應對彩虹表的破解法,但它的安全級別並不高,由於計算哈希值耗時極短,黑客仍然能夠用窮舉法來破解,只是增長了一些耗時。
爲了應對暴力破解法,咱們須要很是耗時的而不是很是高效的哈希算法。BCrypt和PBKDF2算法應運而生。
這兩個算法最大的特色是咱們能夠經過參數設置重複計算的次數,重複計算的次數越多耗時越長。若是計算一個哈希值須要耗時1秒甚至更多,那麼黑客們採用暴利法破解密碼將幾乎再也不可能。破解一個6位純數字密碼須要耗時11.5天,更不要說高安全級別的密碼了。
若是咱們想要儘量保證用戶的信息安全,咱們須要作如下的工做
以上。