一直困擾于HTTP和HTTPS的區(qū)別,現(xiàn)在專門找一個時間來抓住痛點,解決掉該麻煩。
1. HTTP + 加密 + 認(rèn)證 + 完整性保護 = HTTPS
我們知道HTTP是明文傳輸?shù)?,就必不可免存在如下問題:
- 重要數(shù)據(jù)被明文獲取
- 通信雙方可能被偽冒
- 數(shù)據(jù)被篡改
一般獲取簡單數(shù)據(jù)用于展示的,可能無所謂以上的安全缺陷。但假如涉及類似銀行密碼的數(shù)據(jù),就必須慎重考慮這一點了。
所以能夠規(guī)避以上缺陷的HTTP就是HTTPS(HTTP Secure)。
1.1 如何做到加密 + 認(rèn)證 + 完整性保護
我們都知道OSI7層模型,其中HTTP屬于應(yīng)用層協(xié)議,HTTP下一層是TCP(傳輸層協(xié)議)。完全性是一個難題,專注于傳輸速率的傳輸層協(xié)議TCP為了單一職責(zé)的理念,自是不會多管閑事去保證安全性而降低自身的傳輸速率的。
HTTP本身假如要去保證部分?jǐn)?shù)據(jù)的安全性而去專注安全性的開發(fā),也是得不償失。想到這里,很是有一些學(xué)java感受到的職責(zé)單一、職責(zé)分離這樣的思想,哈哈。所以應(yīng)該就是這樣,HTTP與TCP之間再加上一層SSL/TLS(Secure Sockets Layer/Transport Layer Security)協(xié)議。

這樣就算是明白HTTP、HTTPS的區(qū)別了嗎?怎么可能呢?不去搞懂為啥就能安全了、為啥是SSL/TLS這兩個什么東西、為啥用TLS而不是SSL?不搞明白這些問題,怎么能安心呢?
2. SSL/TLS是什么

上一小節(jié)講到,SSL/TLS是HTTP和TCP之間的中轉(zhuǎn)協(xié)議。如圖,可知SSL/TLS也是一個應(yīng)用層的協(xié)議。
那么我們可以把SSL/TLS當(dāng)作一個黑盒子,就像TCP、HTTP,我們知道數(shù)據(jù)先丟給HTTP,HTTP丟給SSL/TLS加密,然后SSL/TLS丟給TCP傳輸...諸如此類,其中具體細(xì)節(jié),暫先不表。
3. SSL和TLS的區(qū)別與歷史
Android 8.0禁用了SSL,所以我們一定非常好奇二者之間的區(qū)別,為什么會有兩種協(xié)議,而且總是并列提起。
SSL是TLS的前身,SSL從1.0、2.0到3.0一步步修訂,但安全性都不是非常完美。知道后來SSL3.0搖身一變變成TLS1.0,發(fā)展至今已經(jīng)達(dá)到TLS1.2的穩(wěn)定版本。另外18年今年,TLS1.3的草案也已經(jīng)提出,在不斷開發(fā)中吧
- SSL 1.0,未發(fā)布公開,因為嚴(yán)重的安全性漏洞
-
SSL 2.0,1995.02,包含一些需要在SSL3.0解決的安全漏洞
SSL 2.0 在2011年被RFC 6176禁止 -
SSL 3.0,1996,代表著該協(xié)議的完整重新設(shè)計,
SSL 3.0也在后來June 2015被RFC 7568禁止. - TLS 1.0 在January 1999首次在RFC 2246中定義,作為SSL 3.0的升級版本
- TLS 1.1April 2006在RFC 4346 中定義
- TLS 1.2August 2008 在 RFC 5246定義,基于TLS 1.1進行升級
所有TLS版本在2011年3月rfc 6176中進一步完善,取消了它們對SSL的向下兼容,TLS再也不支持安全套接字層(SSL)2.0版。
TLS各個版本的更新情況可以看這里 - 維基百科
所以日常提起總是SSL/TLS,TLS是后來的所以放在后面。而維基百科是TLS/SSL,考慮的應(yīng)該是TLS現(xiàn)在是主流吧。我們現(xiàn)在差不多也可以說成是TLS了,畢竟SSL已經(jīng)被禁用了。
以下有幾張圖,可以比較直觀地說明,為什么用TLS,TLS相對于SSL有哪些優(yōu)勢:






最后這一張?zhí)罅?,截不完整,只能管中窺豹了。在此僅僅截下Android部分,畢竟是學(xué)習(xí)Android的。小伙伴們感興趣自己到維基百科查看。
4. TLS/SSL工作機制
4.1 加密方法
共享密鑰方式加密 = 對稱加密 = 處理速度較快
公開密鑰方式加密 = 非對稱加密 = 更復(fù)雜,處理速度較慢
共享密鑰方式加密只要密鑰ok就足夠安全,服務(wù)器只要把密鑰交給客戶端,然后通信過程中和客戶端使用同一把密鑰進行加密解密即可。畢竟是HTTP通信過程肯定是需要速度盡量快才是最好。
Q1:但是共享密鑰如何安全地遞交給對方?比如服務(wù)端如何把共享密鑰安全交給客戶端?
這時候就需要使用公開密鑰方式加密。想用密文和公鑰恢復(fù)到信息原文是異常困難的,相當(dāng)于對離散對數(shù)進行求值,這不是輕而易舉能達(dá)到的。(還是沒有一個很好的概念,總之這很安全就對了)
發(fā)送方使用接收方的公鑰對數(shù)據(jù)進行加密,然后接收方收到密文后使用密鑰對數(shù)據(jù)進行解密。
接上一個問題:通信雙方持有對方的公鑰,發(fā)送共享密鑰時使用公鑰加密,就不怕共享密鑰被獲取了。
Q2:公鑰畢竟是要發(fā)放出去的,如何證明發(fā)給客戶端的過程中,公鑰沒有被替換掉呢?假如公鑰被替換掉,偽冒者就可以假裝成服務(wù)端和用戶進行通信。
接下來就是數(shù)字證書認(rèn)證機構(gòu)出場。
HTTPS中,服務(wù)端將公鑰發(fā)給數(shù)字證書認(rèn)證機構(gòu)進行安全認(rèn)證并對公鑰進行數(shù)字簽名,完成后公鑰和簽名組合成數(shù)字證書。在和客戶端通信時,服務(wù)端將數(shù)字證書發(fā)給客戶端,客戶端通過第三方安全認(rèn)證機構(gòu)發(fā)布的公鑰(一般會在瀏覽器開發(fā)時,內(nèi)置在瀏覽器中)對數(shù)字證書上的簽名進行驗證,假如驗證通過,則能證明以下事實:
- 認(rèn)證該服務(wù)器的公鑰的機構(gòu)是真實有效的數(shù)字證書認(rèn)證機構(gòu)
- 該服務(wù)器發(fā)過來的公鑰是值得信賴的
因為通信雙方都需要證明自己發(fā)出的公鑰真實可靠,所以也就存在兩種目的性不同的數(shù)字證書:可證明組織真實性的EV SSL證書、用以確認(rèn)客戶端的客戶端證書
4.2 工作流程
TCP需要三次握手四次揮手,TLS/SSL也需要握手。

以上這些ClientHello都是報文的名稱,一個箭頭表示一次報文發(fā)送。
- ClientHello:包含支持的TLS最高版本、隨機數(shù)、加密組件(cipher suites)列表、支持的壓縮方法
- ServerHello:根據(jù)ClientHello選擇的TLS版本號、加密組件、壓縮方法,以及隨機數(shù)。假如連接需要從異常關(guān)閉中恢復(fù),還會發(fā)送一個Session id。
- Certificate:包含公鑰證書。(該次報文也可能不發(fā)送,取決于加密組件的選擇)
- ServerKeyExchange:取決于加密組件,所有DHE 和 DH_anon 加密組件都會發(fā)送該報文。但google已經(jīng)棄用DHE加密組件了,所以該報文在《圖解HTTP》一書中甚至沒有提及。
- ServerHelloDone:通知客戶端,最初階段的握手協(xié)商完成了。
- ClientKeyExchange:可能包含稱為PreMasterSecret的隨機密碼串、公鑰或者啥都不包含(取決于使用的加密組件),其中PreMasterSecret會使用Certificate報文中的數(shù)字證書中的公鑰進行加密。
- The client and server then use the random numbers and PreMasterSecret to compute a common secret, called the "master secret". All other key data for this connection is derived from this master secret (and the client- and server-generated random values), which is passed through a carefully designed pseudorandom function.
粗劣翻譯:客戶端和服務(wù)器使用隨機數(shù)和PreMasterSecret,通過精心設(shè)計的偽隨機函數(shù)來計算出一個共同的密鑰,稱為“master secret”。當(dāng)前連接的所有其他密鑰公鑰數(shù)據(jù)都需由master secret(以及客戶端和服務(wù)器生成的隨機值)派生。
- ChangeCipherSpec:告訴服務(wù)端,從現(xiàn)在起所有我發(fā)的信息都會經(jīng)過認(rèn)證了!
- Finished:該報文起就已經(jīng)是加密認(rèn)證過的報文了,其中包含了握手至今全部報文的整體散列值hash和MAC(Message Authentication Code)。服務(wù)端會試圖解密該報文并驗證hash和MAC。如果驗證失敗,這次握手就失敗了,關(guān)閉。
- ChangeCipherSpec:告訴客戶端,從現(xiàn)在起所有我發(fā)的信息都會經(jīng)過認(rèn)證了!
- Finished:客戶端同樣去解密該報文并校驗。解密校驗失敗,一樣會關(guān)閉握手。
- HTTP request/response:接下來就可以進行HTTP的請求了。
- close_notify:最后由客戶端通知服務(wù)端進行關(guān)閉,發(fā)送close_notify報文。當(dāng)然此時關(guān)閉的是TLS連接,繼續(xù)下一層TCP的四次揮手依舊會進行。
還有一個Client-authenticated TLS handshake,翻譯過來差不多是客戶端認(rèn)證的握手流程,和基本流程差不大,就不重新寫一遍了,感興趣的同學(xué)去維基百科看一遍。
至此,總結(jié)一下:通過本文,了解了HTTP和HTTPS之間的區(qū)別、TLS/SSL的歷史發(fā)展、TLS/SSL的工作機制。差不多算是達(dá)到目的了。
可惜水平有限、時間有限,無法深入去追求把加密方面的內(nèi)容深入了。
參考文獻(xiàn):