本文從一個輸入密碼登錄場景說起,詳細介紹了密碼傳輸過程的改進和思路,最后展現出一個相對安全的傳輸和存儲方案。
場景
在互聯網項目中,我們經常會遇到以下場景:
- 用戶注冊,輸入驗證碼傳輸到后端保存
- 用戶登錄,前端輸入密碼傳輸到后端驗證
- 用戶支付,需要輸入支付密碼傳輸到后端驗證
在上述場景中都涉及到了密碼的傳輸和存儲。這就產生了一個問題,密碼作為用戶的敏感數據,我們該采取怎樣的方案才能保證這個過程中的數據安全。
存在的問題
這里我們以登錄場景說起。你可能會說,這多簡單,這不就是前端輸入密碼,然后保存到后端密碼,或者直接從MySQL中查詢出密碼對比一下不就好了嗎?
先說說,如果沒有特殊處理關于密碼的傳輸和存儲會有哪些問題。
- 如果輸入的密碼是明文傳輸到后端,如果中間鏈路被人劫持,那就可以直接竊聽到明文密碼數據。
- 如果數據庫直接存儲明文,黑客攻擊數據庫時就可以輕松獲得明文密碼數據。
因為大多數用戶的常用密碼是固定的,如果拿到用戶的明文數據,影響范圍不只是我們的系統。他們會去其他網站嘗試“撞庫”,很可能會造成用戶的財產損失。作為一個合規的負責任的企業,我們在設計系統時應該考慮這些問題。
為什么會被劫持?
首先說第一個劫持的問題如何解決。
HTTP(超文本傳輸協議)是用于在網絡上傳輸數據的一種協議。雖然HTTP是廣泛使用的協議之一,但它也存在著一些安全風險,例如:
- 竊聽風險:HTTP是明文傳輸協議,數據在傳輸過程中不加密,因此可以被攻擊者竊聽并獲取敏感信息,如用戶名、密碼、銀行卡號等。
- 中間人攻擊:攻擊者可以在傳輸過程中截取數據包并進行篡改或者注入惡意內容,從而實現攻擊。
- XSS(跨站腳本)攻擊:攻擊者利用web應用程序沒有對用戶輸入數據進行過濾或者校驗,從而在用戶瀏覽器中執行惡意腳本或者植入惡意代碼,進而獲取用戶敏感信息或者劫持用戶會話。
- CSRF(跨站請求偽造)攻擊:攻擊者可以通過偽造用戶已認證的請求,以用戶的身份執行惡意操作,例如惡意提交表單、發起請求等。
- 數據篡改:攻擊者可以截獲數據并對其進行修改,從而對web應用程序進行攻擊。
HTTP 存在如此多的安全問題,那么可以替換為 HTTPS 協議來解決。
HTTPS 降低劫持風險
HTTPS(安全套接字層超文本傳輸協議)是HTTP協議的安全版本,通過在傳輸過程中使用加密協議(如SSL或TLS)加密傳輸的數據,避免了明文傳輸的風險,并且使用數字證書驗證服務器的身份,防止冒充攻擊,為Web通信提供了安全保障。HTTPS的主要目的是解決HTTP在傳輸過程中存在的明文傳輸和竊聽風險。
SSL/TLS協議的主要作用是:
- 數據保密性:使用加密算法將數據加密,防止竊聽者獲取敏感信息。
- 數據完整性:使用消息摘要算法和數字簽名等技術來保證數據的完整性,防止數據被篡改。
- 身份認證:使用數字證書來驗證通信對象的身份,防止冒充攻擊。
- 會話管理:SSL/TLS協議支持會話緩存和會話恢復技術,可以提高通信效率,減少計算和網絡資源的消耗。
那么HTTPS請求的完整流程如何,具體是如何保證數據安全的?
- 客戶端向服務器發送請求:客戶端在向服務器發送請求時,將使用HTTPS協議代替HTTP協議,并在請求中包含一個安全連接請求,告知服務器該請求需要使用SSL/TLS協議進行加密和解密。
- 服務器返回數字證書:如果服務器支持HTTPS協議,它將返回一個數字證書,包含服務器公鑰、證書頒發機構等信息。數字證書由可信的第三方機構頒發,用于證明服務器的身份和證書的有效性。
- 客戶端驗證數字證書:客戶端會驗證數字證書的有效性,包括證書是否過期、證書頒發機構是否可信等。如果數字證書通過驗證,客戶端將使用其中的公鑰來建立安全連接。
- 客戶端生成會話密鑰:在與服務器建立安全連接后,客戶端將生成一個會話密鑰(稱為預主密鑰),用于協商加密算法和密鑰長度等參數。這里我們稱為KEY。
- 客戶端將預主密鑰發送到服務器:客戶端將預主密鑰(KEY)使用服務器公鑰進行加密,并將加密后的預主密鑰(KEY)發送到服務器。
- 服務器使用私鑰解密預主密鑰:服務器使用自己的私鑰對預主密鑰(KEY)進行解密,并使用該預主密鑰來協商加密算法、密鑰長度和其他參數。對返回結果內容進行加密后傳輸(這一步就約定好了對稱加密算法,完成對稱密鑰傳輸)
- 客戶端和服務器使用協商的加密算法和密鑰進行通信:在通過以上步驟建立了安全連接并完成了協商過程后,客戶端和服務器將使用協商的加密算法和主密鑰進行通信,保證數據在傳輸過程中的安全性。
以上是HTTPS請求加密的基本過程,其核心是通過數字證書和加密技術來保證數據在傳輸過程中的安全性。整個過程第三方即使監聽到了數據,因為沒有私鑰所以無法解密,如果篡改數據服務器將無法解密。
中間人攻擊
看起來HTTPS似乎解決了網絡傳輸過程中的安全問題,但是HTTPS的安全完全建立在證書可信的基礎上,如果中間人偽造證書怎么辦?
中間人攻擊(Man-in-the-middle attack, MITM攻擊)是指攻擊者在通信雙方之間進行了非法的攔截、篡改和注入操作,從而能夠竊取雙方之間的信息和敏感數據。只要黑客誘導用戶安裝非法證書,他就可以模擬服務器,獲取到用戶傳輸的信息。那么如何解決呢?
加密算法
既然黑客可能獲取到明文數據,那我們加密不就好了嘛。所以,在使用加密算法前我們先簡單了解下加密算法。
加密主要有兩種方式:對稱加密和非對稱加密。
對稱加密
對稱加密是指加密和解密過程使用相同的密鑰,也稱為共享密鑰加密。
- A 使用密鑰加密。
- B 使用相同的密鑰解密。
常見的對稱加密算法有DES、3DES、AES等,其加密速度快、加密效率高,但密鑰的安全性是一個問題,因為加密和解密使用相同的密鑰,如果密鑰被泄露,那么整個通信過程的安全性就會被破壞。
客戶端和服務端進行通信,采用對稱加密,如果只使用一個密鑰,很容易破解;如果每次用不同的秘鑰,海量秘鑰的管理和傳輸成本又會比較高。
算法熱點DES(Data Encryption Standard)數據加密標準,速度較快,適用于加密大量數據的場合,目前已證實不安全,可用3DES替換3DES(Triple DES是基于DES,對一塊數據用三個不同的密鑰進行三次加密,強度更高AES(Advanced Encryption Standard)高級加密標準,是下一代的加密算法標準,速度快,安全級別高,支持128、192、256、512位密鑰的加密。是目前最常見的對稱加密算法
非對稱加密
非對稱加密則使用兩個密鑰:公鑰和私鑰。公鑰可以向任何人公開,用于加密數據,而私鑰只有密鑰的持有者才能使用,用于解密數據。
- A 生成一把公鑰和一把私鑰,公鑰可以給任何人。
- B 拿到公鑰,加密后傳輸給A。
- A 使用私鑰解密。
常見的非對稱加密算法有RSA、DSA、ECC等。非對稱加密算法的安全性很高,因為密鑰是成對出現的,只有私鑰的持有者才能解密數據,而私鑰通常保存在計算機的安全存儲區中,不易泄露。
一般情況下,對稱加密和非對稱加密會結合使用,例如HTTPS協議就同時使用了對稱加密和非對稱加密算法。HTTPS建立連接時使用非對稱加密算法對密鑰進行傳輸,然后使用對稱加密算法來加密數據傳輸,這樣既保證了安全性,又不會影響通信速度。
RSA
RSA加密算法是一種非對稱加密算法,它由Ron Rivest、Adi Shamir和Leonard Adleman三位密學家于1977年共同提出。RSA加密算法的安全性基于數學難題,目前是公認的一種較為安全的加密算法。公鑰私鑰成對出現,用其中一個加密只能用另一個解密,通常用公鑰加密私鑰解密。
為什么RSA能夠做到非對稱加密呢?
互質關系:如果兩個正整數,除了1以外,沒有其他公因子,我們就稱這兩個數是互質關系
簡單來說,RSA利用的原理是,如果兩個互質關系的正整數的乘積足夠大,是極難進行因式分解的(目前被破解的最長RSA密鑰是768個二進制位,而正常使用的至少是1024位的密鑰)。
通過一定的運算,把某計算結果和乘積作為公鑰,另一個計算結果和乘積作為私鑰,即可以實現,利用公鑰進行加密,并利用私鑰進行解密。具體的數學公式推導和證明可以參考RSA算法原理。
繼續改進流程
知道了加密算法的分類,我們果斷采取使用RSA來加密我們的密碼。那么我們將密碼傳輸流程改進為下面這個樣子,將傳輸過程分為獲取公鑰和用公鑰加密兩步,這樣即使有人攔截請求,他也無法解密數據。
存儲加密
現在第一個傳輸密碼的問題已經解決了,那么我們如何存儲密碼呢?
如果用明文存儲密碼(不管是存在數據庫還是日志中),一旦數據泄露,所有用戶的密碼就毫無保留地暴露在黑客的面前,開頭提到的風險就可能發生,那我們費半天勁加密傳輸密碼也失去了意義。
單向加密
單向加密算法指的是只能從明文生成一個對應的哈希值,不能反過來根據哈希值得到對應的明文。經常被大家用來加密的算法有MD5和SHA系列(如SHA1、SHA256、SHA384、SHA512等)。
這樣即使是我們開發人員,拿到數據都不知道用戶的真實密碼,安全性提高了很多,但是還不夠。
通常黑客在侵入保存密碼的數據庫之后,他會隨機猜測一個密碼,生成一個哈希值。如果該哈希值在數據庫中存在,那么他就猜對了一個用戶的密碼。如果沒有猜中也沒有關系,他可以再次隨機猜測下一個密碼進行嘗試。
事實上黑客為了提高破解密碼的效率,他們會事先計算大量密碼對應的各種哈希算法的哈希值,并把密碼及對應的哈希值存入一個表格中(這種表格通常被稱為彩虹表),在破解密碼時只需要到事先準備的彩虹表里匹配即可。因此現在黑客們破解僅僅只用哈希算法加密過的密碼事實上已是不費吹灰之力。
加點“鹽”
鹽salt:一個隨機的字符串,往明文密碼里加鹽就是把明文密碼和一個隨機的字符串拼接在一起。
為了應對黑客們用彩虹表破解密碼,我們可以先往明文密碼加鹽,然后再對加鹽之后的密碼用哈希算法加密。由于鹽在密碼校驗的時候還要用到,因此通常鹽和密碼的哈希值是存儲在一起的,我們需要在數據庫中為其增加對應的字段。這樣我們的密碼就安全多了。
繼續改進我們的流程,如下。
拿到密文密碼并且在服務器解密之后,我們用數據庫中的鹽(每個用戶不同)來拼接明文密碼,然后和數據庫中的密碼做對比,如果相同則登陸成功。
最后,歡迎大家提問和交流。