SSL建立握手連接目的:
1.身份的驗證,client與server確認對方是它相連接的,而不是第三方冒充的,通過證書實現
2.client與server交換session key,用於連接后數據的傳輸加密和hash校驗
簡單的SSL握手連接過程(僅Server端交換證書給client):
1.client發送ClientHello,指定版本,隨機數(RN),所有支持的密碼套件(CipherSuites)
2.server回應ServerHello,指定版本,RN,選擇CipherSuites,會話ID(Session ID)
3.server發送Certificate:服務器將數字證書和到根CA整個鏈發給客戶端,使客戶端能用服務器證書中的服務器公鑰認證服務器
4.Server發送ServerHelloDone
5.Client發送ClientKeyExchange,用於與server交換session key
6.Client發送ChangeCipherSpec,指示Server從現在開始發送的消息都是加密過的
7.Client發送Finishd,包含了前面所有握手消息的hash,可以讓server驗證握手過程是否被第三方篡改
8.Server發送ChangeCipherSpec,指示Client從現在開始發送的消息都是加密過的
9.Server發送Finishd,包含了前面所有握手消息的hash,可以讓client驗證握手過程是否被第三方篡改,並且證明自己是Certificate密鑰的擁有者,即證明自己的身份
下面從抓包數據來具體分析這一過程並說明各部分數據的作用以及如實現前面列出的握手的目標,當然了,最重要的還是說明為何這一過程是安全可靠的,第三方無法截獲,篡改或者假冒
1.client發送ClientHello
每一條消息都會包含有ContentType,Version,HandshakeType等信息。
ContentType指示SSL通信處於哪個階段,是握手(Handshake),開始加密傳輸(ChangeCipherSpec)還是正常通信(Application)等,見下表
Hex |
Dec |
Type |
0x14 |
20 |
ChangeCipherSpec |
0x15 |
21 |
Alert |
0x16 |
22 |
Handshake |
0x17 |
23 |
Application |
Version是TLS的版本,見下表
Major Version |
Minor Version |
Version Type |
3 |
0 |
SSLv3 |
3 |
1 |
TLS 1.0 |
3 |
2 |
TLS 1.1 |
3 |
3 |
TLS 1.2 |
Handshake Type是在handshanke階段中的具體哪一步,見下表
Code |
Description |
0 |
HelloRequest |
1 |
ClientHello |
2 |
ServerHello |
11 |
Certificate |
12 |
ServerKeyExchange |
13 |
CertificateRequest |
14 |
ServerHelloDone |
15 |
CertificateVerify |
16 |
ClientKeyExchange |
20 |
Finished |
ClientHello附帶的數據隨機數據RN,會在生成session key時使用,Cipher suite列出了client支持的所有加密算法組合,可以看出每一組包含3種算法,一個是非對稱算法,如RSA,一個是對稱算法如DES,3DES,RC4等,一個是Hash算法,如MD5,SHA等,server會從這些算法組合中選取一組,作為本次SSL連接中使用。
2.server回應ServerHello
這里多了個session id,如果SSL連接斷開,再次連接時,可以使用該屬性重新建立連接,在雙方都有緩存的情況下可以省略握手的步驟。
server端也會生成隨機的RN,用於生成session key使用
server會從client發送的Cipher suite列表中跳出一個,這里挑選的是RSA+RC4+MD5
這次server共發送的3個handshake 消息:Serverhello,Certificate和ServerHelloDone,共用一個ContentType:Handshake
3.server發送Certificate
server的證書信息,只包含public key,server將該public key對應的private key保存好,用於證明server是該證書的實際擁有者,那么如何驗證呢?原理很簡單:client隨機生成一串數,用server這里的public key加密(顯然是RSA算法),發給server,server用private key解密后返回給client,client與原文比較,如果一致,則說明server擁有private key,也就說明與client通信的正是證書的擁有者,因為public key加密的數據,只有private key才能解密,目前的技術還沒發破解。利用這個原理,也能實現session key的交換,加密前的那串隨機數就可用作session key,因為除了client和server,沒有第三方能獲得該數據了。原理很簡單,實際使用時會復雜很多,數據經過多次hash,偽隨機等的運算,前面提到的client和server端得RN都會參與計算。
4.Server發送ServerHelloDone
5.Client發送ClientKeyExchange
client拿到server的certificate后,就可以開始利用certificate里的public key進行session key的交換了。從圖中可以看出,client發送的是130字節的字節流,顯然是加過密的。client隨機生成48字節的Pre-master secret,padding后用public key加密就得到這130字節的數據發送給server,server解密也能得到Pre-master secret。雙方使用pre-master secret, "master secret"常量字節流,前期交換的server端RN和client的RN作為參數,使用一個偽隨機函數PRF,其實就是hash之后再hash,最后得到48字節的master secret。master secret再與"key expansion"常量,雙方RN經過偽隨機函數運算得到key_block,PRF偽隨機函數可以可以仿佛循環輸出數據,因此我們想得到多少字節都可以,就如Random偽隨機函數,給它一個種子,后續用hash計算能得到無數個隨機數,如果每次種子相同,得到的序列是一樣的,但是這里的輸入時48字節的master secret,2個28字節的RN和一個字符串常量,碰撞的可能性是很小的。得到key block后,算法,就從中取出session key,IV(對稱算法中使用的初始化向量)等。client和server使用的session key是不一樣的,但只要雙方都知道對方使用的是什么就行了。這里會取出4個:client/server加密正文的key,client/server計算handshake數據hash的key。
6.Client發送ChangeCipherSpec
client指示Server從現在開始發送的消息都是加密過的
7.Client發送Finished
client發送的加密數據,這個消息非常關鍵,一是能證明握手數據沒有被篡改過,二也能證明自己確實是密鑰的擁有者(這里是單邊驗證,只有server有certificate,server發送的Finished能證明自己含有private key,原理是一樣的)。client將之前發送的所有握手消息存入handshake messages緩存,進行MD5和SHA-1兩種hash運算,再與前面的master secret和一串常量"client finished"進行PRF偽隨機運算得到12字節的verify data,還要經過改進的MD5計算得到加密信息。為什么能證明上述兩點呢,前面說了只有密鑰的擁有者才能解密得到pre-master key,master key,最后得到key block后,進行hash運算得到的結果才與發送方的一致。
8.Server發送ChangeCipherSpec
Server指示client從現在開始發送的消息都是加密過的
9.Server發送Finishd
與client發送Finished計算方法一致。server發送的Finished里包含hash給client,client會進行校驗,如果通過,說明握手過程中的數據沒有被第三方篡改過,也說明server是之前交換證書的擁有者。現在雙方就可以開始后續通信,進入Application context了。