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






