RSA與SSL淺析

HTTPS = HTTP + SSL

HTTP協議是明文傳輸的,也就是說當數據包使用HTTP協議進行傳輸的時候,如果數據包中途被截下來了,那麼裏面的數據(明文)就會完全暴露。因此,如果數據包裏面存放着用戶的帳號和密碼,就可以認爲用戶的帳號和密碼已經泄漏了。
HTTPS協議則使用了SSL對數據進行加密,即使數據被攔截下來,如果沒有解密的密鑰,也無法得知用戶的數據。

RSA

RSA是一種非對稱加密的算法,所謂非對稱加密算法,就是用於加密解密的密鑰有兩個,即公鑰和私鑰,用公鑰加密過的數據,只有私鑰才能解密,用私鑰加密過的數據,只有公鑰才能解密。(對稱加密算法就是說用於加密解密的只有一個密鑰,密鑰既能加密數據,又能解密數據)
公鑰是可以公開的,別人知道也無所謂,私鑰則要存儲在安全的地方,不能泄漏。

考慮一下在客戶端與服務器之間RSA的應用場景。

  • 客戶端向服務器發送數據
    • 因爲服務器的公鑰是公開的,所以客戶端很容易就能獲取得到服務器的公鑰。客戶端利用服務器的公鑰加密數據,這些數據只有存儲在服務器的私鑰才能解密。
  • 服務器向客戶端發送數據
    • 服務器在向客戶端發送數據的時候,除了用私鑰加密以外,還要生成一個數字簽名。
    • 什麼是數字簽名?服務器會使用hash函數對向客戶端發送的數據生成一個摘要(digest),然後用服務器的私鑰加密這一個digest,得到的就是數字簽名了。
    • 當客戶端拿到服務器發送的數據後,對數據使用相同的hash函數加密一遍,和用公鑰解密的digest進行對比,如果核對一致則說明中途傳輸的數據沒有被篡改。
  • 考慮第三種情況,如何確保你拿到的服務器公鑰確實是正確的服務器的公鑰呢? 即有人將其他的服務器的公鑰給了客戶端,使客戶端誤以爲自己在跟正確的服務器進行交互。(攻擊者可以在代理服務器層攔截客戶端的請求,再重定向到自己的服務器)
    • 這時候我們需要一個權威的第三方機構(CA)確認這一個公鑰確實是真實的服務器的公鑰,服務器將自己的公鑰和一些私人信息發給CA,CA用自己的私鑰將這些數據加密之後就是數字證書(SSL證書)。
    • 當服務器向客戶端發送數據的時候,還附帶上從CA下載到本地的證書,客戶端拿到證書以後使用CA的公鑰進行解密,確認服務器的公鑰無誤。

客戶端與服務器最終交互流程如下:
Https請求流程

RSA的運用場景:SSH

SSH遠程登錄主要有兩種登錄類型:口令登錄以及密鑰登錄。

  • 口令登錄
    • 客戶端首先發出登錄請求,服務器返回一個公鑰,客戶端使用公鑰對登錄密碼進行加密,傳輸給服務器後,服務器使用私鑰對登錄密碼解密然後覈對。
  • 密鑰登錄
    • 客戶端發出登錄請求之後,服務器隨機發送一段字符串,客戶端使用自己的私鑰加密之後返回給服務器,服務器使用存儲的客戶端的公鑰進行解密,解密成功則登錄成功。

有幾點SSH文件放置注意的地方:

  • 客戶端存放服務器公鑰的地方在.ssh/known_hosts。
  • 服務器存放客戶端公鑰的地方在.ssh/authorized_keys。

如果使用密鑰登錄可以使用ssh-copy-id命令,不過要注意權限問題。

SSL

SSL是基於非對稱加密的原理,在這之上還進行了對稱加密的數據傳輸。當傳送數據量過大的時候,客戶端和服務器之間互相商定了一個對話密鑰(session key),使用這個對話密鑰來進行對稱加密加快運算速度。

整個SSL的流程如下:

  • 客戶端向服務器請求證書,驗證無誤後拿到服務器的公鑰
  • 雙方協商生成一個session key
  • 最後雙方採用session key進行加密通信

主要關注前兩步,即SSL的握手階段。

  1. Client Hello
    • 客戶端向服務器發出一個隨機數,以及支持的傳輸協議以及加密算法 ,壓縮方法。
  2. Server Hello
    • 服務器在確認支持客戶端的傳輸協議等要求後,發送服務器的證書,以及一個隨機數,安全需求更高的服務器會要求客戶端發送證書來證明客戶端的身份。
  3. 客戶端迴應
    • 客戶端此時生成第三個隨機數(這一個隨機數被稱爲pre-master-key),向CA驗證服務器的證書以後拿到服務器的公鑰,使用公鑰加密第三個隨機數,並把加密後的第三個隨機數發送給服務器。
    • 客戶端在本地利用之前與服務器商量好的加密方法,根據這三個隨機數生成一個對話密鑰(session key)用於兩端通信。
  4. 服務端迴應
    • 服務端收到第三個隨機數後,計算出對話密鑰,至此,握手階段結束。接下來使用對話密鑰進行通信即可。

這裏參考這篇博客中的一張表示SSL運行機制的圖片:
SSL運行機制

SSL證書籤名申請(CSR)

在購買了SSL證書以後,需要把證書和域名綁定起來。一般的證書是隻能用在一個域名上,不過端口不限制。

如果希望子域名都能使用HTTPS可以考慮入手一個通配型的SSL證書,或者子域名個數不多的時候可以使用UCC類型的SSL證書。UCC類型的SSL證書是指一個證書可以加密指定數量的網站,在配置證書的時候往SAN裏面添加額外的域名即可。

在服務器端使用openssl命令生成一個csr爲後綴的文件(同時還有你的服務器私鑰key文件),然後上傳或者粘貼CSR文件內容至購買域名的網站:

openssl req -new -newkey rsa:2048 -nodes -keyout 您的域名.key -out 您的域名.csr

筆者購買的是GoDaddy的域名證書,該網站還提供了詳細的Nginx的CSR配置文件指導,傳送門如下:
生成 NGINX CSR(證書籤名申請)

在提交CSR文件後CA會確認你是否擁有對這個域名的所有權,Godaddy提供了兩種驗證方法:

  • 首先,Godaddy會發送一封郵件,郵件裏包含了要顯示的指定內容。

    • 第一種方法 ,如果沒有對域名的管理權,但是擁有域名映射到的服務器的所有權,將指定內容做成HTML文件,並上傳至域名映射的服務器的根目錄等待Godaddy確認。

    • 第二種方法,如果擁有對域名的管理權,則在域名解析裏面添加TXT類型的DNS記錄,記錄值就爲指定內容,等待Godaddy確認。

  • 域名所有權或者管理權驗證完畢之後,即可下載SSL證書。

筆者在Godaddy下載證書之後得到兩個證書(兩個crt文件),其中有一個帶有bundle命名的中間證書,需要把兩個證書串聯在一起得到一個最終證書。

$ cat first.crt bundle.crt > example.com.crt

Nginx配置HTTPS

非常簡單,只需要在監聽的端口上加上SSL配置就好了。

server {  
    listen 9999 ssl;
    server_name example.com;

    ssl on;
    ssl_certificate /root/.ssl/example_com.crt;
    ssl_certificate_key /root/.ssl/example_com.key;
}

參考資料:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章