接上篇:到這裏,“客戶”就可以確認“服務器”的身份,並且雙方的通信內容可以進行加密,其他人就算截獲了通信內容,也無法解密。
的確,好像通信的過程是比較安全了。
但是這裏還留有一個問題,在最開始我們就說過,“服務器”要對外發布公鑰,那“服務器”如何把公鑰發送給“客戶”呢?我們第一反應可能會想到以下的兩個方法:
a)把公鑰放到互聯網的某個地方的一個下載地址,事先給“客戶”去下載。
b)每次和“客戶”開始通信時,“服務器”把公鑰發給“客戶”。
但是這個兩個方法都有一定的問題,
對於a)方法,“客戶”無法確定這個下載地址是不是“服務器”發佈的,你憑什麼就相信這個地址下載的東西就是“服務器”發佈的而不是別人僞造的呢,萬一下載到一個假的怎麼辦?另外要所有的“客戶”都在通信前事先去下載公鑰也很不現實。
對於b)方法,也有問題,因爲任何人都可以自己生成一對公鑰和私鑰,他只要向“客戶”發送他自己的私鑰就可以冒充“服務器”了。示意如下:
“客戶”->“黑客”:你好 //黑客截獲“客戶”發給“服務器”的消息
“黑客”->“客戶”:你好,我是服務器,這個是我的公鑰 //黑客自己生成一對公鑰和私鑰,把公鑰發給“客戶”,自己保留私鑰
“客戶”->“黑客”:向我證明你就是服務器
“黑客”->“客戶”:你好,我是服務器 {你好,我是服務器}[黑客自己的私鑰|RSA] //客戶收到“黑客”用私鑰加密的信息後,是可以用“黑客”發給自己的公鑰解密的,從而會誤認爲“黑客”是“服務器”
因此“黑客”只需要自己生成一對公鑰和私鑰,然後把公鑰發送給“客戶”,自己保留私鑰,這樣由於“客戶”可以用黑客的公鑰解密黑客的私鑰加密的內容,“客戶”就會相信“黑客”是“服務器”,從而導致了安全問題。這裏問題的根源就在於,大家都可以生成公鑰、私鑰對,無法確認公鑰對到底是誰的。 如果能夠確定公鑰到底是誰的,就不會有這個問題了。例如,如果收到“黑客”冒充“服務器”發過來的公鑰,經過某種檢查,如果能夠發現這個公鑰不是“服務器”的就好了。
爲了解決這個問題,數字證書出現了,它可以解決我們上面的問題。先大概看下什麼是數字證書,一個證書包含下面的具體內容:
- 證書的發佈機構
- 證書的有效期
- 公鑰
- 證書所有者(Subject)
- 簽名所使用的算法
- 指紋以及指紋算法
2.5 第五回合:
“客戶”->“服務器”:你好
“服務器”->“客戶”:你好,我是服務器,這裏是我的數字證書 //這裏用證書代替了公鑰
“客戶”->“服務器”:向我證明你就是服務器
“服務器”->“客戶”:你好,我是服務器 {你好,我是服務器}[私鑰|RSA]
注意,上面第二次通信,“服務器”把自己的證書發給了“客戶”,而不是發送公鑰。“客戶”可以根據證書校驗這個證書到底是不是“服務器”的,也就是能校驗這個證書的所有者是不是“服務器”,從而確認這個證書中的公鑰的確是“服務器”的。後面的過程和以前是一樣,“客戶”讓“服務器”證明自己的身份,“服務器”用私鑰加密一段內容連同明文一起發給“客戶”,“客戶”把加密內容用數字證書中的公鑰解密後和明文對比,如果一致,那麼對方就確實是“服務器”,然後雙方協商一個對稱加密來保證通信過程的安全。到這裏,整個過程就完整了,我們回顧一下: