HTTPS 簡介
在日常互聯(lián)網(wǎng)瀏覽網(wǎng)頁時,我們接觸到的大多都是 HTTP 協(xié)議,這種協(xié)議是未加密,即明文的。這使得 HTTP 協(xié)議在傳輸隱私數(shù)據(jù)時非常不安全。因此,瀏覽器鼻祖 Netscape 公司設(shè)計了 SSL(Secure Sockets Layer) 協(xié)議,用于對 HTTP 協(xié)議傳輸進行數(shù)據(jù)加密,即 HTTPS 。
HTTPS 和HTTP 協(xié)議相比提供了:
- 數(shù)據(jù)完整性:內(nèi)容傳輸經(jīng)過完整性校驗
- 數(shù)據(jù)隱私性:內(nèi)容經(jīng)過對稱加密,每個連接生成一個唯一的加密密鑰
- 身份認(rèn)證:第三方無法偽造服務(wù)端(客戶端)身份
SSL 目前版本是 3.0,之后升級為了 TLS(Transport Layer Security) 協(xié)議,TLS 目前為 1.2 版本。如未特別說明,SSL 與 TLS 均指同一協(xié)議。
HTTPS 工作原理
網(wǎng)絡(luò)通信(握手過程)
此圖非常詳盡的描述了 HTTPS 在通訊過程中的原理,總共分為 8 步。

STEP 1: 客戶端發(fā)起HTTPS 請求
SSL 連接總是由客戶端啟動,在 SSL 會話開始時,執(zhí)行 SSL 握手。用戶在瀏覽器里輸入一個https 網(wǎng)址,然后連接到server 的443 端口。
客戶端發(fā)送以下:
- 列出客戶端密支持的加密方式列表(以客戶端首選項順序排序),如 SSL 的版本、客戶端支持的加密算法和客戶端支持的數(shù)據(jù)壓縮方法(Hash 算法)。
- 包含 28 字節(jié)的隨機數(shù),
client_random
以下是 Wireshark 抓包所得
Transmission Control Protocol, Src Port: 28258 (28258), Dst Port: 443 (443), Seq: 1, Ack: 1, Len: 517
Source Port: 28258
Destination Port: 443
[Stream index: 13]
[TCP Segment Len: 517]
......
Secure Sockets Layer
TLSv1 Record Layer: Handshake Protocol: Client Hello
// 握手記錄
Content Type: Handshake (22)
// 0x0301 可以看出 TLS 是基于 SSL 3.1 構(gòu)建而來
Version: TLS 1.0 (0x0301)
Length: 512
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 508
Version: TLS 1.2 (0x0303)
Random
GMT Unix Time: Jun 20, 2025 23:30:57.000000000 ?й???????
// 28 字節(jié)隨機數(shù) client_random
Random Bytes: 12154d457c935c162fb8c0062572a5f84639b06289c51bf2...
Session ID Length: 32
// 可能為空,如果之前登陸過,則可以恢復(fù)之前的會話,避免一個完整的握手過程
Session ID: c958100d8b678c0b071b54e977b456c06a233c08b9e2dd42...
Cipher Suites Length: 34
// 密文族,列舉瀏覽器所支持的加密算法清單
Cipher Suites (17 suites)
Cipher Suite: Unknown (0xcca9)
Cipher Suite: Unknown (0xcca8)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcc14)
Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcc13)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
// 推薦使用
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
Compression Methods Length: 1
Compression Methods (1 method)
Compression Method: null (0)
Extensions Length: 401
Extension: renegotiation_info
Type: renegotiation_info (0xff01)
Length: 1
Renegotiation Info extension
Renegotiation info extension length: 0
Extension: server_name
Type: server_name (0x0000)
Length: 36
Server Name Indication extension
Server Name list length: 34
Server Name Type: host_name (0)
Server Name length: 31
// 允許服務(wù)器對瀏覽器的請求授予相應(yīng)的證書。
Server Name: images-cn.ssl-images-amazon.com
Extension: Extended Master Secret
Type: Extended Master Secret (0x0017)
Length: 0
Extension: SessionTicket TLS
Type: SessionTicket TLS (0x0023)
Length: 192
Data (192 bytes)
Extension: signature_algorithms
Type: signature_algorithms (0x000d)
Length: 18
Signature Hash Algorithms Length: 16
// Hash 算法,用于簽名
Signature Hash Algorithms (8 algorithms)
Signature Hash Algorithm: 0x0601
Signature Hash Algorithm Hash: SHA512 (6)
Signature Hash Algorithm Signature: RSA (1)
Signature Hash Algorithm: 0x0603
Signature Hash Algorithm Hash: SHA512 (6)
Signature Hash Algorithm Signature: ECDSA (3)
Signature Hash Algorithm: 0x0501
Signature Hash Algorithm Hash: SHA384 (5)
Signature Hash Algorithm Signature: RSA (1)
Signature Hash Algorithm: 0x0503
Signature Hash Algorithm Hash: SHA384 (5)
Signature Hash Algorithm Signature: ECDSA (3)
Signature Hash Algorithm: 0x0401
Signature Hash Algorithm Hash: SHA256 (4)
Signature Hash Algorithm Signature: RSA (1)
Signature Hash Algorithm: 0x0403
Signature Hash Algorithm Hash: SHA256 (4)
Signature Hash Algorithm Signature: ECDSA (3)
Signature Hash Algorithm: 0x0201
Signature Hash Algorithm Hash: SHA1 (2)
Signature Hash Algorithm Signature: RSA (1)
Signature Hash Algorithm: 0x0203
Signature Hash Algorithm Hash: SHA1 (2)
Signature Hash Algorithm Signature: ECDSA (3)
Extension: status_request
Type: status_request (0x0005)
Length: 5
Certificate Status Type: OCSP (1)
Responder ID list Length: 0
Request Extensions Length: 0
Extension: signed_certificate_timestamp
Type: signed_certificate_timestamp (0x0012)
Length: 0
Data (0 bytes)
Extension: Application Layer Protocol Negotiation
Type: Application Layer Protocol Negotiation (0x0010)
Length: 14
ALPN Extension Length: 12
ALPN Protocol
ALPN string length: 2
ALPN Next Protocol: h2
ALPN string length: 8
ALPN Next Protocol: http/1.1
Extension: channel_id
Type: channel_id (0x7550)
Length: 0
Data (0 bytes)
Extension: ec_point_formats
Type: ec_point_formats (0x000b)
Length: 2
EC point formats Length: 1
Elliptic curves point formats (1)
EC point format: uncompressed (0)
Extension: elliptic_curves
Type: elliptic_curves (0x000a)
Length: 8
Elliptic Curves Length: 6
Elliptic curves (3 curves)
Elliptic curve: Unknown (0x001d)
Elliptic curve: secp256r1 (0x0017)
Elliptic curve: secp384r1 (0x0018)
Extension: Padding
Type: Padding (0x0015)
Length: 77
Padding Data: 000000000000000000000000000000000000000000000000...
Padding length: 0
Padding Data: <MISSING>
STEP 2: 服務(wù)端的配置
采用HTTPS 協(xié)議的服務(wù)器必須要有一套數(shù)字證書,可以自己制作,也可以向組織申請。區(qū)別就是自己頒發(fā)的證書需要客戶端驗證通過,才可以繼續(xù)訪問,而使用受信任的公司申請的證書則不會彈出提示頁面。這套證書其實就是一對公鑰和私鑰。
** 如果對公鑰和私鑰不太理解,可以想象成一把鑰匙和一個鎖頭,只是全世界只有你一個人有這把鑰匙,你可以把鎖頭給別人,別人可以用這個鎖把重要的東西鎖起來,然后發(fā)給你,因為只有你一個人有這把鑰匙,所以只有你才能看到被這把鎖鎖起來的東西。** 客戶端和服務(wù)器至少必須支持一個公共密碼對,否則握手失敗。服務(wù)器一般選擇最大的公共密碼對。
STEP 3: 傳送證書
服務(wù)器端返回以下:
- 服務(wù)器端選出的一套加密算法和 Hash 算法
- 服務(wù)器生成的隨機數(shù)
server_random -
SSL數(shù)字證書(服務(wù)器使用帶有SSL的X.509 V3數(shù)字證書),這個證書包含網(wǎng)站地址,公鑰public_key,證書的頒發(fā)機構(gòu),過期時間等等。
Transmission Control Protocol, Src Port: 443 (443), Dst Port: 28258 (28258), Seq: 1, Ack: 518, Len: 137
Source Port: 443
Destination Port: 28258
[Stream index: 13]
[TCP Segment Len: 137]
Sequence number: 1 (relative sequence number)
[Next sequence number: 138 (relative sequence number)]
Acknowledgment number: 518 (relative ack number)
Header Length: 20 bytes
Flags: 0x018 (PSH, ACK)
......
Secure Sockets Layer
TLSv1 Record Layer: Handshake Protocol: Server Hello
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301)
Length: 81
Handshake Protocol: Server Hello
Handshake Type: Server Hello (2)
Length: 77
Version: TLS 1.0 (0x0301)
Random
GMT Unix Time: Mar 1, 2090 17:07:25.000000000 ?й???????
// 28 字節(jié)的隨機數(shù) server_random
Random Bytes: 903945ed14db8e4151d651814ed7067c0e9c115d94ff6af7...
Session ID Length: 32
Session ID: c958100d8b678c0b071b54e977b456c06a233c08b9e2dd42...
// 加密族中,服務(wù)器最終選擇了這個。意味著服務(wù)器之后會使用 RSA 公鑰加密算法來區(qū)分證書簽名和交換密鑰,通過 3DES 加密算法來加密數(shù)據(jù),通過 SHA 算法來校驗信息
Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
Compression Method: null (0)
Extensions Length: 5
Extension: renegotiation_info
Type: renegotiation_info (0xff01)
Length: 1
Renegotiation Info extension
Renegotiation info extension length: 0
TLSv1 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
Content Type: Change Cipher Spec (20)
Version: TLS 1.0 (0x0301)
Length: 1
Change Cipher Spec Message
[Expert Info (Note/Sequence): This session reuses previously negotiated keys (Session resumption)]
[This session reuses previously negotiated keys (Session resumption)]
[Severity level: Note]
[Group: Sequence]
TLSv1 Record Layer: Handshake Protocol: Encrypted Handshake Message
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301)
Length: 40
Handshake Protocol: Encrypted Handshake Message
STEP 4: 客戶端解析證書
這部分工作是由客戶端的TLS 來完成的。
- 首先會驗證證書是否有效,這是對服務(wù)端的一種認(rèn)證,比如頒發(fā)機構(gòu),過期時間等等,如果發(fā)現(xiàn)異常,則會彈出一個警告框,提示證書存在問題。
- 如果證書沒有問題,那么瀏覽器根據(jù)步驟 3 的
server_random生成一個隨機值premaster_secret(前 2 個字節(jié)是協(xié)議版本號,后 46 字節(jié)是用在對稱加密密鑰的隨機數(shù)字)和master_secret 。 master_secret的生成需要premaster_key,并需要client_random和server_random作為種子
現(xiàn)在,各方面已經(jīng)有了主密鑰master_secret = PRF(pre_master_secret, "master secret", client_random + server_random)master_secret,根據(jù)協(xié)議約定,我們需要利用PRF生成這個會話中所需要的各種密鑰,稱之為“密鑰塊”(Key Block ):
這是由系列 Hash 值組成,它將作為數(shù)據(jù)加解密相關(guān)的Key Material ,包含六部分內(nèi)容,分別是用于校驗一致性的密鑰,用于對稱內(nèi)容加解密的密鑰,以及初始化向量,客戶端和服務(wù)器端各一份。其中,key_block = PRF(SecurityParameters.master_secret, "key expansion", SecurityParameters.server_random + SecurityParameters.client_random); 密鑰塊用于構(gòu)成以下密鑰: client_write_MAC_secret[SecurityParameters.hash_size] server_write_MAC_secret[SecurityParameters.hash_size] client_write_key[SecurityParameters.key_material_length] server_write_key[SecurityParameters.key_material_length] client_write_IV[SecurityParameters.IV_size] server_write_IV[SecurityParameters.IV_size]write MAC key,就是session secret或者說是session key。Client write MAC key是客戶端發(fā)數(shù)據(jù)的session secret,Server write MAC secret是服務(wù)端發(fā)送數(shù)據(jù)的session key。MAC(Message Authentication Code),是一個數(shù)字簽名,用來驗證數(shù)據(jù)的完整性,可以檢測到數(shù)據(jù)是否被串改。然后用證書公鑰public_key對該隨機值進行加密。就好像上面說的,把隨機值用鎖頭鎖起來,這樣除非有鑰匙,不然看不到被鎖住的內(nèi)容。 - Hash 握手信息,用第3步返回約定好的 Hash 算法對握手信息取 Hash 值,然后用隨機數(shù)加密“握手消息+握手消息 Hash 值(簽名)”
STEP 5: 傳送加密信息
客戶端發(fā)送以下:
- 客戶端發(fā)送公鑰
public_key加密的premaster secret。目的就是讓服務(wù)端得到這個隨機值,以后客戶端和服務(wù)端的通信就可以通過這個隨機值來進行加密解密了。
STEP 6: 服務(wù)端解密信息
服務(wù)端用私鑰 private_key 解密后,得到了客戶端傳過來的隨機值 premaster_secret(私鑰),又由于服務(wù)器在步驟 1 中收到的 client_random ,所以服務(wù)器根據(jù)相同的生成算法,在相同輸入?yún)?shù)的情況下,得到相同的 master_secret 。然后把內(nèi)容通過該值進行對稱加密。
所謂對稱加密就是,將信息和私鑰通過某種算法混合在一起,這樣除非知道私鑰,不然無法獲取內(nèi)容,而正好客戶端和服務(wù)端都知道這個私鑰,所以只要加密算法夠彪悍,私鑰夠復(fù)雜,數(shù)據(jù)就夠安全。
STEP 7: 傳輸加密后的信息
服務(wù)器端返回以下:
將被 premaster_key 對稱加密的信息返回客戶端,客戶端可還原
STEP 8: 客戶端解密信息
客戶端用之前生成的私鑰解密服務(wù)段傳過來的信息,于是獲取了解密后的內(nèi)容。整個過程第三方即使監(jiān)聽到了數(shù)據(jù),也束手無策。
SSL/TLS

HTTPS 可以認(rèn)為是 HTTP + TLS。TLS 是傳輸層加密協(xié)議TLS 協(xié)議本身又是由 record 協(xié)議傳輸?shù)模瑀ecord 協(xié)議的格式如下圖

TLS 協(xié)議主要有五種類型 Content Type:
Content types
| Hex | Dec | Type |
|---|---|---|
| 0x14 | 20 | 加密消息確認(rèn)協(xié)議 ChangeCipherSpec |
| 0x15 | 21 | 報警協(xié)議 Alert |
| 0x16 | 22 | 握手協(xié)議 Handshake |
| 0x17 | 23 | 應(yīng)用數(shù)據(jù)層協(xié)議 Application |
| 0x18 | 24 | 心跳協(xié)議 Heartbeat |
加密方式
加密算法一般分為對稱加密與非對稱加密。
對稱加密
客戶端與服務(wù)器使用相同的密鑰對消息進行加密
優(yōu)點:
- 加密強度高,很難被破解
- 計算量小,僅為非對稱加密計算量的 0.1%
缺點:
- 無法安全的生成和管理密鑰
- 服務(wù)器管理大量客戶端密鑰復(fù)雜
非對稱加密
非對稱指加密與解密的密鑰為兩種密鑰。服務(wù)器提供公鑰,客戶端通過公鑰對消息進行加密,并由服務(wù)器端的私鑰對密文進行解密。
優(yōu)點:安全
缺點
- 性能低下,CPU 計算資源消耗巨大,一次完全的 TLS 握手,密鑰交換時的非對稱加密解密占了整個握手過程的 90% 以上。而對稱加密的計算量只相當(dāng)于非對稱加密的 0.1%,因此如果對應(yīng)用層使用非對稱加密,性能開銷過大,無法承受。
- 非對稱加密對加密內(nèi)容長度有限制,不能超過公鑰的長度。比如現(xiàn)在常用的公鑰長度是 2048 位,意味著被加密消息內(nèi)容不能超過 256 字節(jié)。
HTTPS 下的加密
HTTPS一般使用的加密與HASH算法如下:
- 非對稱加密算法:
RSA,DSA/DSS - 對稱加密算法:
AES,RC4,3DES - HASH算法:
MD5,SHA1,SHA256
其中非對稱加密算法用于在握手過程中加密生成的密碼,對稱加密算法用于對真正傳輸?shù)臄?shù)據(jù)進行加密,而HASH算法用于驗證數(shù)據(jù)的完整性。由于瀏覽器生成的密碼是整個數(shù)據(jù)加密的關(guān)鍵,因此在傳輸?shù)臅r候使用了非對稱加密算法對其加密。非對稱加密算法會生成公鑰和私鑰,公鑰只能用于加密數(shù)據(jù),因此可以隨意傳輸,而網(wǎng)站的私鑰用于對數(shù)據(jù)進行解密,所以網(wǎng)站都會非常小心的保管自己的私鑰,防止泄漏。
TLS握手過程中如果有任何錯誤,都會使加密連接斷開,從而阻止了隱私信息的傳輸。正是由于HTTPS非常的安全,攻擊者無法從中找到下手的地方,于是更多的是采用了假證書的手法來欺騙客戶端,從而獲取明文的信息,但是這些手段都可以被識別出來
關(guān)于證書
證書需要申請,并由專門的數(shù)字證書認(rèn)證機構(gòu) CA 通過非常嚴(yán)格的審核之后頒發(fā)的電子證書,證書是對服務(wù)器端的一種認(rèn)證。頒發(fā)的證書同時會產(chǎn)生一個私鑰和公鑰。私鑰有服務(wù)器自己保存,不可泄露,公鑰則附帶在證書的信息中,可以公開。證書本身也附帶一個證書的電子簽名,這個簽名用來驗證證書的完整性和真實性,防止證書被篡改。此外證書還有個有效期。
證書包含以下信息:
- 使用者的公鑰值。
- 使用者標(biāo)識信息(如名稱和電子郵件地址)。
- 有效期(證書的有效時間)。
- 頒發(fā)者標(biāo)識信息。
- 頒發(fā)者的數(shù)字簽名,用來證明使用者的公鑰和使用者的標(biāo)識符信息之間的綁定的有效性。
參考資料
[1] Wiki 關(guān)于 Transport Layer Security 的介紹,https://en.wikipedia.org/wiki/Transport_Layer_Security
[2] 大型網(wǎng)站的 HTTPS 實踐(一)—— HTTPS 協(xié)議和原理 http://op.baidu.com/2015/04/https-s01a01/
[3] SSL工作原理 https://www.wosign.cn/Basic/howsslwork.htm
[4] SSL/TLS協(xié)議運行機制的概述 http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
[5] HTTPS工作原理,貓尾博客,https://cattail.me/tech/2015/11/30/how-https-works.html
[6] HTTPS那些事(一)HTTPS原理,曉風(fēng)殘月,http://www.guokr.com/post/114121/
[7] HTTPS證書生成原理和部署細節(jié),小胡子哥,http://www.barretlee.com/blog/2015/10/05/how-to-build-a-https-server/