總結DH密鑰協商(會話密鑰)

密鑰安全性

在對稱加密中,無論加密解密,通信雙方都是使用相同的密鑰,如果其中一方密鑰泄露了,信息便會遭到破解。使用公開密鑰雙向加密可以極大提高安全性,通信雙方手握對方的公鑰進行信息加密,保留自己的私鑰進行解密,從客戶端發去的加密信息即使被中途截獲,沒有私鑰的話也無法解密,而私鑰保存在服務器端,相反一樣。這樣將密鑰對分成公鑰和私鑰的方式,比起對稱加密共同使用相同的密鑰,明顯更安全。無論是對稱加密還是公開密鑰,安全性關鍵都是在於密鑰的長度,例如上一篇日誌講到的公開密鑰,它是怎麼生成公鑰的?是兩個大質數相乘後結果n,和隨機數e組成的,如果要解出私鑰,首先就要得到這兩個大質數,可以通過對n進行因式分解,不過只要這兩個大質數足夠大,對其進行因式分解是十分困難的。

傳輸問題

在密鑰本身的安全性得到保證後,還不夠,因爲密鑰是要發送給通信對方的,如果在發送密鑰的時候被截獲,那麼前面做的一切都是徒勞。通常一個服務器端會接收處理多個客戶端,雙方建立連接後,開始消息發送,爲了保證信息安全性,會使用相應的加密措施,無論是對稱加密害死公開密鑰,都需要發送密鑰給對方進行加密解密,那麼在發送密鑰過程中,怎麼保證密鑰安全不泄露?

如果只是幾人十幾人的小組內進行互相通信,那麼可以簡單地通過外部方式例如郵件方式傳輸密鑰,而不在通信線路上傳輸。可是對於C/S模式下服務器端需處理許多的客戶端連接,但是服務器端並不知道這些客戶端來自誰,沒有辦法通過外部如郵件的方式發送密鑰,只能就彼此建立的連接線路上進行通信,怎麼辦?怎麼把密鑰安全地通過這條線路發送到客戶端?

 

密鑰協商算法

密鑰協商算法可以解決上面提到的兩個問題,生成安全的密鑰,和安全的傳輸,還能解決密鑰存儲問題。密鑰存儲問題,簡單來說,假如我們把密鑰保存在本地磁盤中,每次加密解密都出本地獲取密鑰,那麼就幾乎沒什麼泄露的問題,但如果我們把密鑰保存在是數據庫中,數據庫泄露便等於密鑰泄露了。回到正題,看看密鑰協商如何解決密鑰安全生成,傳輸和存儲三部分問題。

會話密鑰

上面說到,一個服務器端需要處理很多很多的客戶端連接,如果我們爲每一個連接都保存一個固定的不同的密鑰,那麼存儲量將十分龐大,但是我們又不能讓它們使用統一的密鑰,這顯然是不安全的,要解決這個問題,可以用到會話密鑰的方式。會話密鑰就是在本次通信中使用的一次性密鑰,當通信結束後密鑰就失效了,等下一次建立連接時會生成不同的會話密鑰,會話密鑰僅在本次通信期內有效。在我們訪問https協議的網址,即https://開始的網址時,我們的瀏覽器會和服務器之間使用SSL/TLS協議進行加密通信,用到的就是會話密鑰。會話密鑰是存儲在客戶端和服務器端的內存中的,當通信結束後,會話密鑰失效,便會從內存中丟棄,解決了上面的密鑰存儲問題。

看到這裏你可能想,雖然每次通信都更換密鑰,但還是沒有解決密鑰傳輸問題啊,建立連接生成會話密鑰後,不還是要先發送密鑰給對方嗎?接下來就是看密鑰的生成過程,你會知道它是怎麼保證密鑰傳輸的安全性的。

DH密鑰協商

DH(Diffie-Hellman)密鑰協商的做法是讓通信雙方在通信上交換彼此的信息來共同計算出相同的會話密鑰,即使中間一部分傳遞信息被截獲,也無法根據其計算出會話密鑰,因爲計算會話密鑰的另一部分信息在接收方處,而接收方並沒有公開這部分信息,因此中間方並不會有足夠的信息來得到會話密鑰,進而破解之後的通信密文。在看DH密鑰協商的處理過程前,先來看DH算法的密鑰文件是怎麼樣的:

其中,p是一個大質數,g則是一個小整數,一個公鑰和一個私鑰,接下來服務器端和客戶端都會根據這些參數生成各自的密鑰對,然後協商出會話密鑰。

可以看到,通常由服務器端生成DH密鑰文件參數,在客戶端和服務器端建立連接後,密鑰協商過程可以歸納爲:

  1. 客戶端發送請求DH參數,服務器端生成DH密鑰文件參數,包括p,g,公鑰spub和私鑰spri。

spub = (g^spri)mod p;

  1. 服務器端發送參數p,g以及公鑰spub給客戶端,客戶端接收後,先是自己生成一個私鑰cpri,然後根據參數p,g,服務器端公鑰spub和自己的私鑰cpri計算得出客戶端公鑰cpub。

cpub = (g^cpri)mod p;

  1. 客戶端將公鑰cpub發送給服務器端,服務器端根據客戶端公鑰cpub和自己的私鑰spri計算得到會話密鑰。

M = (cpub^spri)mod p;

  1. 客戶端根據私鑰cpri和服務器端公鑰spub計算得到會話密鑰。密鑰協商完成。

M = (spub^cpri)mod p;

由上面的過程可以看到,生成會話密鑰的關鍵是服務器端和客戶端自己的私鑰,這兩個私鑰是各自生成的,並不會發送出去,即使中間放拿到了客戶端和服務器端的公鑰以及參數p,g,也沒辦法計算出會話密鑰。看到這裏你可能會想,從上面的密鑰協商過程可以看到,服務器端是需要發送參數p和g的,並且之後雙方還會交換公鑰,拿客戶端處舉例,客戶端的公鑰等於cpub = (g^cpri)mod p,那麼帶入公鑰,g和p不就可以計算出客戶端私鑰cpri?

安全性-離散對數

表達式中4個參數,擁有了3個,看似是很容易能求出那唯一的未知數,但是我們看它的算法,g^x mod p,求x的過程就是離散對數,如果是數值很小的情況下,8^x mod 5 = 4,當然可以很輕易求出x=2,但是我們看回求公鑰的表達式中,p是一個大質數,通常在1024字節或以上,私鑰也是一個很大的數,因爲密鑰越長安全性越高,對這樣大的數字做離散是很難的,上一篇日誌說到,目前已被破解的最大二進制位爲768個二進制位。

來看看使用這種方式實現密鑰協商的過程:

  1. 服務器端生成DH密鑰參數p和g,假設p是43,g是7。再生成一個隨機數作爲密鑰spri,假設爲9。計算服務器端公鑰併發送給客戶端:

spub = 7^9 mod 43 = 42。

  1. 客戶端接收到DH密鑰參數和公鑰spub後,自己生成一個隨機密鑰cpri,假設爲8,並計算出客戶端公鑰,發回給服務器:

cpub = 7^8mod 43 = 6。

  1. 服務器端計算出會話密鑰:

M = (cpub^spri)mod p;

6^9 mod 43 = 1;(商爲234365)

  1. 客戶端計算出會話密鑰:

42^8 mod 43 = 1;(商爲225177953405)

 

完整示例

一個完整的DH密鑰協商過程,首先由通信雙方任意一方生成DH密鑰參數文件dhparam.pem。接着通信雙方各自生成自己的密鑰對,並分離出公鑰和私鑰,私鑰自己保存,公鑰發送給對方,最後雙方根據對方發來的公鑰和自己的私鑰協商出會話密鑰,可以看到,雙方的會話密鑰是一樣的。

 

完整命令已上傳:

https://github.com/justinzengtm/Network-Engineering

發佈了101 篇原創文章 · 獲贊 73 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章