離開後端說前端加密都是空談

最近有朋友在使勁研究如何不使用 HTTPS 的狀況下保護用戶密碼安全。暫且不說研究過程,但結論是要保障安全必須後端參與,使用非對稱加密算法 —— 如此一來,不如直接用 HTTPS 更簡單便捷有保障。使用免費 SSL 證書,一年一換,運維稍微麻煩一點,訪問稍微慢一點(證書認證過程好像會慢一些),但至少是專業的,比本身研究的沒通過大量檢驗的算法靠譜多了。前端

假設已經作過必要的安全防範,目前惟一須要解決的問題是保障用戶密碼在 HTTP 的明文傳輸過程當中不被竊取。爲達此目的,研究過程以下:算法

對稱算法加密密碼

若是說,密碼在明文傳輸過程當中存在風險,最直接的解決辦法是讓密碼再也不是原來的樣子。使用一個 KEY 來加密密碼,再將加密後的結果傳輸到後臺,由後臺解密使用。數據庫

image.png

看起來確實起做用,若是竊取到加密後的密碼數據,沒有 KEY 是不能解密出來的。然而KEY 要用於前端加密,就必定會存在於前端的某個地方,而前端的全部資源都是用戶能夠獲取並分析的,甚至可使用瀏覽器的開發者工具經過各類調試手段來分析獲取。因此 KEY 自己並不能安全保存,安全性被打破。segmentfault

此外,若是 secure_data 在傳輸過程被竊取,是能夠重複使用的(由於 KEY 不變,加密結果就不會變),這也是一個不安全因素。後端


結論 📚

使用對稱加密算法來加密密碼的方式不能保證密鑰安全,也不能保證用戶密碼安全,更不能保護註冊/登陸過程安全。瀏覽器

對密碼進行單純的 HASH

使用對稱加密,在密文和密鑰都被竊取的時候,能夠解出密碼原文,對用戶在其餘系統中(可能使用了相同密碼)形成威脅。爲此,咱們可使用不可逆的 HASH 算法來處理密碼,只要先後端計算方式相同,不須要解密出密碼原文,直接使用 HASH 結果就行。緩存

用戶註冊時,假設咱們有原密碼 my_password,使用 MD5 計算後是 a865a7e0ddbf35fa6f6a232e0893bea4。這個 HASH 送到後端以後,後端是不能從 HASH 反算出原密碼的,因此後端只能直接保存這個 HASH。安全

那麼驗證的時候,一樣將原密碼計算成 HASH a865a7e0ddbf35fa6f6a232e0893bea4,傳輸到後端,後端拿它和保存的數據進行對比,相同則驗證經過。服務器

有問題嗎?固然有,你看 ——運維

使用 Hash 的過程

image.png

不使用 HASH 的過程

image.png

從傳輸過程開始,Hash 前的過程和 Hash 後的過程並無區別。對於偷竊者來講,無所謂是拿到的 my_password 仍是 a865a7...,只要把它送到後端,就能成功登陸。

因此這種作法並不能保護用戶登陸!

不過密碼是採用 Hash 計算過的,是否是能保護用戶密碼不會竊取用於嘗試登陸其餘系統呢?也不能!

一些常見的密碼,好比 123456 採用 MD5 計算後是 e10adc3949ba59abbe56e057f20f883e,拿這個 Hash 上百度就能查出來原密碼是 123456。固然,專業人士會有專業的工具,也就是彩虹表(什麼是彩虹表?查查唄!),數以 TB 計的數據,可能大部分密碼都查得出來吧。


結論 📚

從前端對密碼進行單純的 HASH 算法,起不到任何保護做用。

其實從後端對密碼進行單純的 HASH 加密也只能起到很弱的保護做用,幾近裸奔。

引入密鑰,使用 HMAC

HMAC 比單純的 HASH 算法,要多一個密鑰因素,能夠認爲是加密的 HASH。使用 HMAC 能夠有效的阻礙彩虹表破解。所以使用 HMAC 保護用戶密碼原文。可是,若是傳輸的是 HMAC 計算結果,和前面的討論同理,並不能保護登陸。

但使用 HMAC 和單純的 HASH 又有那麼一點不一樣。假設咱們已經經過其餘方式進行安全的註冊,後端已經保存了用戶密碼 my_password,來看看下面這個登陸過程:

image.png

攻擊者只須要竊取 hash_result 便可仿冒登陸,而 hmac_result 在傳輸過程當中能夠輕鬆竊取。

此外,還有一個不安全點:固化在腳本中的 secure_key 是能夠從拉到客戶的腳本資源中分析出來的。


結論 📚

使用固定 secure key 的 HMAC 算法並不能保障登陸安全,只能起到保密用戶密碼原文的做用。可是,因爲 secure_key 很容易被拿到,因此對密碼原文的保護也相對較弱。

引入動態安全碼 (secure key)

繼續尋找解決辦法,咱們能夠想到一個改進方案:若是知足下面兩個條件,上面遇到的問題彷佛就能解決:

  • secure_key 並非固定在腳本中,而是動態產生的,就能夠解決從腳本分析得到 secure_key 的問題;
  • 這個 secure_key 使用 1 次後當即失效,那麼 hmac_result 就不能用於再一次登陸,能夠解決 hmac_result 被竊取複用的問題。

動態 secure_key 看起來是個不錯的辦法,可是它應該在哪裏動態產生呢?

若是在前端動態產生,就必須通知後端,傳輸的數據須要包含 secure_keyhmac_result 兩部分。他們都能被竊取使用。這種狀態下若是要保證 secure_key 只能使用一次,就必需要後端緩存全部用過的 secure_key 備查 —— 顯然這會極大的增長後端負擔。所以,不能夠由前端來產生動態安全碼。

image.png

用後端產生動態安全碼以後能夠當即緩存起來,同時傳輸給前端(這個過程能夠前端發起請求)。前端按上述步驟對用戶密碼進行加密,將數據送回後端。後端檢查 secure_key 在緩存中,取出來計算用於驗證的 hmac_result,同時從緩存中刪除 secure_key;若是 secure_key 不在緩存中,直接拒絕驗證。

image.png

引入動態 secure_key 解決了登陸期間驗證用戶密碼的問題。

雖然數據在傳輸過程當中仍然能被竊取,可是被竊取的數據不能重複使用,也不易破解出密碼原文(可花長時間暴力破解),因此這個方案是初步可行的 —— 但要注意,它可能會受中到中間人攻擊。

此外,該方案是不完整的,由於它只能解決驗證密碼(登陸)的問題,不能解決保存密碼(註冊)的問題 —— 注意到後端是直接從數據庫加載的 my_password,這意味着在註冊時須要傳入密碼原文或者可解密出密碼原文的密文 —— 這在以前的研究中都還沒找到辦法。


結論 📚

後端產生一次性使用的動態 secure_key 能夠保障登陸安全,但不能解決註冊安全。並且該方案須要注意防禦中間人攻擊

注意:須要後端參與

使用非對稱加密

到目前爲止,咱們總算找到一個前端登陸勉強可用的安全方案。接下來還要研究用戶註冊時該怎麼辦。

註冊時須要傳輸可解密的密文,並且在前端不能找到可用於解密的密鑰 —— 這個場景很是符合非對稱加密的應用場景 —— 前端使用公鑰加密,後端使用私鑰解密,問題就能獲得完美解決:

image.png


結論 📚

使用非對稱加密算法,能夠保護用戶密碼安全,也能夠保護登陸過程安全。可是要注意中間人攻擊

注意:須要後端參與

使用 HTTPS

到此爲止,咱們已經很是接近 HTTPS 了。HTTPS 主要就是採用的非對稱加密算法來保證數據傳輸安全。爲了防止中間人攻擊還引入了公信機構(受信任的證書中心)。可是,這個安全過程的參與方,包括 HTTPS 使用的安全協議(SSL 和 TSL 等)、服務器、公信機構、用戶本身等,均可能成爲整個安全過程的短板。

做爲專業保障 HTTP 傳輸安全的 HTTPS 協議都隨時在曝漏洞,請問,你又哪裏來的信心憑一已之力用本身的安全算法實現來代替 HTTPS?若是沒有足夠的能力,仍是安心用 HTTPS 吧!


邊城客棧

請關注公衆號邊城客棧

看完了先別走,點個贊 ⇓ 啊,讚揚 ⇘ 就更好啦!

相關文章
相關標籤/搜索