第一章. 對SSL的基本概念和框架的介紹 · Client 處理和回應(yīng) Server Hello 階段 客戶端收到服務(wù)器發(fā)過來的那些消息,要做的是驗(yàn)證服務(wù)器證書,發(fā)送自己的證書(如果雙向認(rèn)證),發(fā)送計算出的預(yù)主密碼,發(fā)送證書驗(yàn)證消息。
收到 Server Hello 在 server hello 階段連續(xù)的發(fā)了多個消息,最先發(fā)出的是 server hello , client 收到后將 SSL 會話 ID ,服務(wù)器端的一個隨機(jī)數(shù),協(xié)商出的SSL 協(xié)議版本號以及密鑰套件放到會話緩存中。
收到 Server Certificates 接下來收到的應(yīng)該是 server 端的證書消息了,取出所有的消息,最頭上的是 server 證書,最末端的 CA 根證書。在 SUN JDK JSSE 中實(shí)現(xiàn)的SSL 是這樣處理的: 從 SSLContex 中取出 trust manager ,如果用過 java SSL 編程的同學(xué)應(yīng)該知道,可以自己實(shí)現(xiàn) X509TrustManager 和 X509KeyManager 兩個接口來定制對證書的驗(yàn)證, sun jdk 中就是調(diào)用這個 trust manager 的驗(yàn)證方法來驗(yàn)證證書(在解決瀏覽器檢測到證書是自簽名的時候跳出警告框的問題就是可以自己實(shí)現(xiàn)這個 trust manager 來讓瀏覽器不跳出警告框)。
JDK 當(dāng)然也有默認(rèn)的證書驗(yàn)證實(shí)現(xiàn),就是驗(yàn)證簽名有效性,驗(yàn)證證書是否過期等。證書簽名的有效性驗(yàn)證是在取證書鏈中某證書中的公鑰驗(yàn)證前一個證書的簽名,這樣第一個證書就是用第二個證書的公鑰來驗(yàn)證,那有人可能會問最后的根 CA 的證書誰來驗(yàn)證?根 CA 的證書是自簽名的,就是自己給自己簽名,沒人管的了, JDK 中某個文件中有存儲一堆可信任的證書發(fā)行機(jī)構(gòu)的證書列表,如果你的根 CA 在那個列表中并對比后確實(shí)是那個根 CA 的證書那就 OK ,驗(yàn)證通過,這個可信任的機(jī)構(gòu)也可以自己實(shí)現(xiàn)那個 trust manager 來添加設(shè)置。
收到 Server Key Exchange 消息 RSA 方式密鑰交換消息則把消息中的加密用公鑰放入會話緩存中,作為客戶端這邊握手階段的寫密鑰而不是用服務(wù)器證書中的公鑰。 DH 方式的消息就把消息中的 p,g,Ys 三個參數(shù)記錄下來,有這些 client 端就可以計算出 pre-master 了,只要回頭再把自己這邊的 Yc 參數(shù)發(fā)過去, server 端就也能計算出相同的 pre-maseter 了。
收到 server Certtificats Request 消息 將消息中的證書類型列表和可信任證書發(fā)行機(jī)構(gòu)列表保存下來,可在后面發(fā)送客戶端證書時候拿來篩選證書用。
收到 Server Hello Done 消息 收到這個消息后 client 端開始向 server 發(fā)消息了
發(fā)送 Client Certificates 消息 如果是 server 端要求客戶端認(rèn)證就會發(fā)這個消息,否則不發(fā)??蛻舳丝赡軙卸鄠€證書,在 JSSE 里頭多個客戶端證書存儲在 keystore 里頭,選哪個發(fā)過去呢?這時候要用到 server 端之前發(fā)的 cert request 消息中的支持的證書類型列表和信任的根 CA 列表,滿足這個兩個條件的第一個證書鏈就會被選中作為客戶端證書。
發(fā)送 Client Key Exchange 消息 若是 RSA 方式密鑰交換,則產(chǎn)生一個 48 位隨機(jī)數(shù)作為 pre-master 并用服務(wù)器公鑰加密后發(fā)出去 若是 DH 方式的密鑰交換,則根據(jù) sever 的 g,p,Ys ,產(chǎn)生 Xa 和 Yc , Xa 和 Ys 能計算出 pre-master ,把產(chǎn)生的 Yc 放入消息中發(fā)給server ,這樣 server 用它的 Xb 和 Yc 也能計算出 pre-master 了。計算出預(yù)主密碼后就順便把主密碼 (master secret) 給算出來了。算出主密碼就把對稱密鑰產(chǎn)生出來了。
發(fā)送 Certificate verify 消息 這個消息是可選的,只有在客戶端發(fā)送了自己證書到服務(wù)器端,這個消息才需要發(fā)送。發(fā)這個消息的目的是讓服務(wù)器驗(yàn)證發(fā)消息的客戶端和客戶端證書的真實(shí)所有者。這個消息中要包含一個簽名,簽名里頭內(nèi)容就是從 client hello 開始到目前為止所有握手消息(不包括本消息)的摘要,主密碼,若是 RSA 方式則要把這些內(nèi)容分別用 MD5 和 SHA1 計算一遍,兩種摘要算法算得的摘要拼接起來用客戶端證書中公鑰對應(yīng)的私鑰加密就獲得了簽名。到時候服務(wù)器端會用收到的證書中的公鑰來驗(yàn)證簽名。
發(fā)送 change cipher spec 消息 發(fā)送這個消息,然后把 session 的寫密鑰設(shè)置成計算得到得對稱密鑰,從此消息之后再發(fā)送消息就會用這個寫密鑰來加密消息。
發(fā)送 client Finished 消息 Client 端的 Finished 消息一般都是緊隨 change cipher spec 消息發(fā)送出去,標(biāo)志著本方的 SSL 協(xié)商成功結(jié)束。消息中包含兩個個摘要,是分別用 MD5 和 SHA 算法計算當(dāng)前收到所有握手消息和主密碼的摘要,不包括本消息和 change cipher spec( 因?yàn)椴粚儆谖帐窒?/span> ) 。
該消息是SSL握手中的最后要互傳的消息,包含一個所有握手消息的摘要值,這是為了防止中間人將強(qiáng)度較大的CipherSuite在client hello消息中刪除,使得server不得不選擇強(qiáng)度較小的CipherSuite,然而這非client所愿。問題是這個摘要不可以被中間人更改嗎?想象一下這時共享對稱密鑰已經(jīng)協(xié)商好了,ChangeCipherSpec已經(jīng)經(jīng)過,所以這些消息本身是加過密的。 · Server 處理和回應(yīng) cleint Finished 階段 Server 收到 client 的證書鏈后驗(yàn)證證書,并驗(yàn)證 certificatie verify 中的簽名,驗(yàn)證通過了也就確認(rèn)了 client 的身份,如假包換。收到 client key exchange 消息從中拿出 Pre-master 計算出 master ,生成對稱密鑰。收到 client 的 change cert spec 后將會話的讀密鑰設(shè)置為剛產(chǎn)生的對稱密鑰。 處理完這些 server 會發(fā)送自己的 change cipher spec 消息并把會話的寫密鑰設(shè)置為生成的對稱密鑰,最后發(fā)送 server Finished 消息,client 端收到 server 端的 change cipher spec 消息將會話的讀密鑰設(shè)置為生成的對稱密鑰。到此握手過程圓滿結(jié)束,接下來的應(yīng)用消息將使用設(shè)置好的讀寫密鑰對數(shù)據(jù)加解密。 |
|