安全通訊

昀溪發表於2019-05-11

安全通訊

應用層協議大多數自己都沒有實現加解密功能,比如http等。http就是直接把資料載入進來然後做簡單編碼(也就是流式化)然後響應客戶端,然後資料在瀏覽器展示,這個資料在傳輸過程是明文的,你截獲就可以直接檢視。這顯然不安全,要想做到安全那麼就只能在傳送端加密然後接收端還能把資訊還原成原來的內容,這就是加密解密。其實這個事情很好理解,加密解密在古代就有也不是現代的概念。在安全通訊裡面我經常聽到的2個東西就是SSL和TLS,這2個有什麼區別呢?以及HTTPS是怎麼通訊的?

SSL和TLS

SSL

SSL是網景公司研發的一種功能模組這種模組或者叫庫就在應用層和傳輸層之間又加了一層,而且不是一整層只是半層,這要做的好處是你呼叫這個庫就可以使用這個功能如果不呼叫則還是按照之前的方式來使用,這個半層的庫就是SSL,叫做安全套接字層。不過SSL只是一種規範和協議並不是具體實現。OpenSSL則是對SSL的實現而且眾多實現中的一種。什麼叫做一種實現呢?比如httpd和Nginx這兩個應用都是http協議的實現或者說x86是一種標準那麼DELL和HP都可以基於這種標準來設計自己的電腦。

如果你自己本身不具備開發這種加密解密的功能,那麼你就可以使用SSL完成這個工作,不過無論你自己開發還是使用SSL,這些加密解密協議都需要具備2個基本功能:

  1. 加密和解密

  2. 秘鑰分發

在Web應用方面,http呼叫了ssl就變成了https,雖然就是呼叫了ssl,但是http和https這兩個在機制上有巨大的區別。

TLS

叫做傳輸層安全,為什麼有了SSL還會有一個和SSL類似的TLS呢?因為SSL協議是發明者是網景公司,它擁有版權,而且網際網路公司很多都需要使用安全通訊,所以國際標準化機構就參照SSL弄了一個TLS協議。兩者相容。TLS由IETF在1999年釋出。那麼由於SSL的3個版本有漏洞所有很多不用了。現在主流都使用TLS。總之你可以把TLS當做SSL使用其原理都是一樣的。

早期使用SSL較多後來大部分使用TLS,雖然我們平時會說ssl它可能指的是SSL也可以是TLS,所以你不用糾結它指的是什麼你只要理解為一種安全通訊機制就可以。所以我們後面會不加區分的統稱SSL。

為什麼現在都是全站啟用SSL呢

之前很多網站都不是https,也只有某些特殊階段才使用,比如支付階段、登入驗證階段。那麼後來為什麼大家包括百度搜尋首頁這種都變成https了呢?

如果使用SSL加密那麼服務端就需要解密,加解密其實非常消耗CPU資源,早期處於效能考慮不會大面積使用SSL,比如只是普通的瀏覽網頁沒必要進行安全通訊。但是後來伺服器效能越來越強而且大規模使用x86伺服器以及有些網路卡也支援SSL解除安裝,所以全站使用SSL也成為可能。

不過由於http是明文傳輸的,使用者訪問什麼網頁其實可以透過流量攔截,資料可以被修改,有些不法行為就可以利用這一點來實現廣告投放,但是使用https通訊則不會出現這種情況。

安全通訊到底怎麼安全呢?

基本概念

為了解決安全問題實現安全目標比如保密性、完整性、可用性等其解決方案有兩類,就是技術和服務,技術指的是加密和解密;服務指的是認證機制和訪問控制機制。
針對加密和解密以及實現服務功能的所用到的加密演算法和協議就有如下幾種:對稱加密、非對稱加密、單向加密和認證協議。

在Linux上實現上述演算法和協議的工具有OpenSSL(ssl協議的實現)和GPG(pgp協議的實現)。

數字加密演算法

先說一下演算法,雖然加密用秘鑰但是如何用這個秘鑰來對資料加密或者解密這個是演算法來決定的,但是通常演算法是公開的比如RSA(個別安全公司有自己的獨有的演算法除外)所以是否安全不取決於演算法而是秘鑰。

什麼叫密碼,什麼叫秘鑰?我上面那段話肯定會有人迷糊,密碼是編碼和解碼的規則你可以理解為加密和解密規則而秘鑰則是改變密碼行為的外在引數,也就是說相同的規則當你使用不同的秘鑰加密相同內容時加密後的結果也是不同的。比如字母移位這就是密碼,而移動N位的這個N則是秘鑰。假設移動3位,那麼ABC則變成DEF。所以這就是為什麼上面那段話的結論是不取決於演算法(密碼)而是秘鑰。

對稱秘鑰加密:對稱加密演算法有很多,但是無論什麼演算法加密解密都使用相同的秘鑰,好處是簡單計算量小也就是不會對CPU產生太大壓力,缺點以及密碼過多(你要和很多人通訊就需要很多人的密碼)、密碼分發困難。因為你要讓對方可以解密你就需要把密碼先給對方,這個給密碼的過程要不要加密呢?這就變成了先有雞還是先有蛋的事情永遠扯不清。常用演算法DES(目前已經棄用)、AES等。

非對稱秘鑰加密:有公鑰和私鑰,使用公鑰加密私鑰解密。如果A和B通訊每個人都有一對兒公鑰和私鑰,彼此還都有對方的公鑰。A發資訊給B則使用B的公鑰加密,然後B收到後使用自己的私鑰解密,然後B回覆資訊給A則使用A的公鑰加密,A收到後使用自己的私鑰解密。這個過程看似完美,可是由於公鑰大家都能獲取,B怎麼知道資訊是來自A而不是來自其他冒名A的人呢?這就是數字簽名,這個後面再說。非對稱加密主要用於數字簽名和秘鑰交換。加密資料雖然它也能做但是通常不這麼用,你看後面的HTTPS通訊過程就知道了。非對稱加密主要用來做對稱秘鑰的交換,完成交換後大家其實就是使用對稱密碼來做資料加密和解密。常用演算法RSA(加解密和簽名)、DSA(僅能簽名)等。

單向加密**:不可逆的,只能加密不能解密,比如MD5、SHA1等。其實主要用來提取資料摘要或者說指紋,所以並不能算作我們常規意義上的加密。它的特點是資料微小變化都會導致指紋的不同,所以主要用來做資料完整性驗證。

特別注意:並不是說只能用公鑰加密私鑰解密,非對稱加密方式的目的就是使用一種秘鑰加密的資料必須能使用另外一種秘鑰解密,所以無論是公鑰還是私鑰都可以加密,我們之所以說用公鑰加密用私鑰解密是首先是因為公鑰是從私鑰中提取出來的,其次公鑰是公開的如果你用私鑰加密那麼任何擁有該私鑰對應公鑰的人都可以解密 。所以才有公鑰發給其他人私鑰自己留存且用公鑰加密私鑰解密,因為只有這樣才能發揮這種非對稱加密或者說公鑰加密的主要作用也就是密碼交換和數字簽名。不過使用私鑰加密資料可以證明一件事情就是如果用該私鑰的公鑰可以解密那就證明這個資料一定是私鑰持有人發來的。

秘鑰交換(IKE,網際網路秘鑰交換):IKE實現的方式有公鑰加密和DH演算法。這種標準主要用來做秘鑰交換。不過對於秘鑰交換來說更加安全的其實是DH演算法,雖然常用的是公鑰加密方式。

公鑰加密最大的問題是密碼是要從一方傳送到一方,雖然使用對方的公鑰加密了。但是DH的好處是雙方不用發密碼而且雙方還可以得到密碼。

數字簽名

數字簽名的主要作用是為了檢查資料是否被篡改以及資料是誰發的(就是向對方證明此時他收到的訊息是來自訊息宣稱的人本人而不是冒名頂替的第三人,當然真正驗證對方身份的還不能僅僅靠數字簽名這個後面再說)。

按照上面的例子A發訊息給B,A使用B的公鑰加密,B透過自己的私鑰解密,可是公鑰大家都可以獲得那麼B怎麼知道這個訊息是來自A呢?難道僅僅憑藉訊息內容說我是A就斷定訊息來自A麼?另外B怎麼確定資訊在傳遞過程中沒有被篡改呢?

為了解決這個問題A對訊息做雜湊摘要(MD5演算法或者SHA1演算法等)然後用A自己的私鑰對摘要進行加密(數字簽名),然後把加密後的摘要和訊息本身一起使用B的公鑰加密傳送給B,這樣B收到訊息後用自己的私鑰可以解密,然後用A的公鑰可以解密簽名(上面提到的摘要)如果成功就說明訊息來自A。這就是簽名和驗證簽名過程。訊息來源確認了,此時就會擔心訊息傳遞過程中如果被篡改怎麼辦?這就是那段被加密的摘要的作用,如果B使用相同的演算法來計算資訊的摘要,如果B計算得到的值和解密簽名後的得到的值一致說明資訊沒有被篡改。

上面的過程的確看起來很好但是有一個漏洞就是所有的公鑰都要自己儲存和管理萬一被別人替換了呢,或者說A和B從未通訊過現在要做第一次通訊如何把公鑰給對方呢?難道就不怕有人冒充A把自己的公鑰給了B那麼反過來也是一樣,另外A對資訊做雜湊摘要的時候用的什麼演算法,萬一B沒有這個演算法怎麼辦呢,所以這就引出了CA和證書的概念。

為什麼需要CA、證書以及CA根證書

公鑰加密私鑰解密,私鑰肯定是自己儲存其實也就儲存一份,如果我需要給很多人通訊難道我要儲存很多人的公鑰麼?如果這個數量達到一個量級在管理上也很困難另外就是如何防止公鑰被篡改呢也就是如何驗證這個公鑰是不是我要通訊的那個人的公鑰而不是別人發來冒充他的。如果要是有一個第三方機構來統一管理就好了,這就是CA證書管理機構。CA的作用就是對申請人的公鑰進行認證和加密,加密後的公鑰就是數字證書,又稱CA證書,證書中包含了很多重要資訊比如申請人、用途、申請人支援的加密演算法、申請人使用hash演算法,證書有效期等其中最重要的就是證書申請人的公鑰。當然前提是通訊雙方都要信任同一個CA機構。

那有了CA之後該怎麼做呢?申請者需要自己生成自己的公鑰和私鑰,然後把公鑰和其他申請資訊發給證書頒發機構,證書頒發機構自己也有公鑰和私鑰,然後證書頒發機構提取申請者的公鑰和其他資訊的特徵碼,然後CA使用自己的私鑰加密這個特徵碼也就是簽名, 這樣形成一個由CA簽名的證書然後傳送給申請者 。此時還是A和B通訊且為第一次通訊並且雙方都信任同一CA頒發機構 。

  1. A把自己支援的對稱加密演算法、單向加密演算法、公鑰加密演算法以及自己的證書發給B
  2. B拿到資訊後需要對A的證書解密(這樣才能獲取A的公鑰),但證書是CA用私鑰加密的需要用CA的公鑰解密這怎麼辦?這就是CA根證書(包含CA的公鑰)的作用,B需要下載CA根證書並且安裝到自己的電腦裡通常只需要安裝一次(通常現在作業系統 MacOX、Windows都已經內建了國際著名CA的根證書,因為全球著名CA都是有限的,Linux沒有內建)。有了這個根證書也就有了CA的公鑰,這樣就可以解密A的證書來獲取A的公鑰。能解密成功說明A的證書是CA頒發的。然後使用證書中的單向加密演算法來計算證書的特徵碼如果和解密簽名得到的特徵碼一致則表明內容沒有被篡改,所以這一步完成了對A的身份驗證和證書資訊的完整性驗證。
  3. 驗證完之後還要看該證書的有效期以及證書主體名稱和該證書是否被吊銷
  4. 驗證都透過之後B選擇自己支援的對稱加密演算法、單向加密演算法、公鑰加密演算法以及自己的證書傳送給A
  5. A採用相同的步驟來驗證B,如果驗證透過,這時候大家就確定了使用哪種對稱加密演算法、單向加密演算法、公鑰加密演算法並且完成了雙方的公鑰交換以及身份驗證
  6. A使用對稱加密演算法生成一個密碼,然後對密碼計算摘要,然後用自己的私鑰對摘要進行簽名,之後用B的公鑰進行加密傳送給B
  7. B收到資訊後使用自己的私鑰解密,然後使用A的公鑰解密簽名得到摘要,如果解密成功則說明是A發來的,然後對密碼提取摘要並和解密簽名得到的摘要對比,如果一直則說明資訊完整,這時候就完成了密碼交換,從此雙發就可以使用對稱加密方式來通訊。

上述這個過程就是大家透過CA來間接獲取通訊雙方公鑰的過程。如果B使用CA的根證書無法解密A發來的證書說明就說明A的證書不是該CA簽發的,由於世界上公認的CA也就那麼幾個所以如果B用這些CA的根證書都解密不了A的證書,那麼就會提示風險,很有可能A這個證書就是一個自簽名的證書。

這裡我們只是闡明概念,在實際應用中上述過程還有些不同,比如上面A發給B的包括簽名和證書以及資訊,難道資訊不加密麼?如果加密用什麼加密等。這些東西都會在具體應用場景中再說明。

既然明白了CA那麼我們就說一下PKI。

PKI

公鑰基礎設施,以CA為中心所生成的一套體系就是PKI。它有四個重要元件:

  • 簽證機構,就是CA,這個是負責生成證書的

  • 序號產生器構,就是RA,這個是負責接收證書申請的

  • 證書吊銷列表,就是CRL,這個是標記哪些證書已經不可用或者不可信了,相當於證書黑名單,這裡的證書都不能被信任了。

  • 證書存取庫,就是CB,這裡存放的是CA發的證書可以供其他人下載和使用

證書常用欄位和格式

首先要說一下X.509,它就是證書標準,也叫做證書格式。所有證書都要符合這個標準,它定義了證書中包含那些內容。比如版本號、序列號(CA發的第幾個證書)、簽名演算法ID(這個證書用什麼演算法做的簽名)、CA頒發機構名稱、證書有效期、申請者名稱、申請者公鑰、CA頒發機構的唯一標識、申請者的唯一標識、CA對該證書的簽名(用CA自己的私鑰對所有資訊的摘要做簽名)等擴充套件資訊。下面就看看證書中常見的欄位:

欄位 含義
Common Name 簡稱CN,對於SSL證書來說一般為網站域名;而對於程式碼簽名證書則為申請單位名稱;而對於客戶端證書來說則是申請者名稱也可以當做使用者賬號名稱
Organization Name 簡稱O,對於SSL證書來說一般為網站域名;而對於程式碼簽名證書則為申請單位名稱;而對於客戶端證書來說則是申請者名稱也可當做使用者賬號所屬的組
Locality 簡稱L,表示城市
State/Provice 簡稱ST,表示省份
Country 簡稱C,表示國家,比如中國為CN,美國為US

瀏覽器使用HTTPS訪問時它是怎麼檢查證書和位址列中的名稱呢?有下面三種方式

  1. 主機名(位址列中的域名)與證書Subject中的CN欄位完全匹配
  2. 主機名稱與萬用字元通用名稱相匹配,比如www.abc.com匹配通用名稱*.abc.co
  3. 主機名在主題備用名稱(Subject Alternative Name檢查sans)欄位中列出

我們知道了X.509是證書格式,可是很多時候看到的.pem、.key都什麼呢?,這裡就要做一些區分,證書編碼格式和證書副檔名。

證書編碼格式

所有的證書都是透過X.509標準生成的證書,但是有2中編碼格式:

  • PEM(Privacy Enhanced Mail),它是基於X.509標準生成的,檔案可讀可以直接開啟檢視,它是以"-----BEGIN CERTIFICATE-----" 和 "-----END CERTIFICATE-----"開頭和結尾且用Base64編碼的證書,這種編碼格式的證書通常是.pem副檔名。

    使用命令 openssl x509 -in XXX.pem -text -noout 來檢視證書內容。

  • DER(Distinguished Encoding Rules),二進位制格式的,無法直接讀取。

    使用命令 openssl x509 -in XXX.der -inform der -noout 來檢視證書內容。

證書副檔名

雖然證書編碼格式有2種,但是副檔名有很多:

副檔名 說明
.der 用於DER編碼的證書
.pem 它是基於X.509標準生成的,它是以"-----BEGIN CERTIFICATE-----" 和 "-----END CERTIFICATE-----"開頭和結尾且用Base64編碼的證書
.crt 這種副檔名的證書可以是DER編碼也可以是PEM編碼,在Unix系統中常見。
.cer 微軟系統常見,在微軟系統中可以將.crt轉換為.cer。同樣可以是DER編碼也可以是PEM編碼。
.key 用於儲存公鑰和私鑰,同樣可以使用DER或者PEM編碼。
.csr 這個不是證書檔案,而是證書籤名請求檔案,向CA申請獲得簽名證書時需要提供的申請檔案。

HTTPS通訊過程

雙向認證

上圖為SSL的雙向驗證過程

  1. 瀏覽器發起https請求,生成隨機數(用於稍後生成會話秘鑰),併傳送client_hello資訊裡面將自己支援的加密協議版本、加密演算法、壓縮演算法和生成的隨機數傳送給服務端。
  2. 服務端收到資訊以後,也生成隨機數(用於稍後生成會話秘鑰),併傳送server_hello信確認自己客戶端傳送來的協議版本、演算法等。如果不支援那麼就無法通訊了。
  3. 服務端傳送伺服器證書給客戶端,並且要求客戶端也傳送證書過來
  4. 客戶端檢查服務端證書合法性和有效性,透過以後,傳送客戶端證書給服務端
  5. 伺服器檢查客戶端的證書合法
  6. 客戶端把所有之前收到的資訊做HASH,然後使用自己私鑰做簽名,傳送給伺服器端
  7. 服務端檢查雜湊值和簽名
  8. 客戶端使用對稱加密演算法生成一個加密密碼,然後使用客戶端公鑰進行加密傳送給服務端
  9. 服務端收到以後就可以使用對稱加密密碼和客戶端通訊
  10. 斷開連線

單向認證

HTTPS訪問通常使用單向認證,比如你訪問百度、淘寶、京東等雖然是https通訊但是它們不會去驗證客戶端證書,客戶端只會去驗證服務端證書。為什麼呢?因為證書花錢啊,哪個網站要是需要做客戶端證書認證那麼估計就沒有人去訪問了,再有對於服務端來說它不在乎你是誰來的人越多越好。當然也有通訊雙方要求做雙向認證的比如登入網銀的U盾就是客戶端證書。

  1. 瀏覽器發起https請求,生成隨機數將自己支援的一套加密規則、協議版本傳送給服務端。

  2. 服務端從中選出一組加密演算法與HASH演算法,服務端也生成一個隨機數並將自己的身份資訊以證書的形式發回給瀏覽器。證書裡面包含了服務端地址,加密公鑰,以及證書的頒發機構等資訊。

  3. 客戶端獲得服務端證書之後瀏覽器要做以下工作:(驗證我訪問的www.abc.com是不是真正的那個www.abc.com,這個驗證過程就透過服務端證書和自己的CA根證書來完成)

    • 驗證證書的合法性和有效性(使用客戶端儲存的CA根證書的公鑰解密服務端發來的證書的簽名,解密成功說明服務端證書可以信任,然後使用HASH演算法計算證書摘要然後對比解密簽名後得到的摘要,如果一致則說明內容沒有篡改,然後 檢查證書中的其他資訊,可以檢查證書中的域名和我訪問的域名是否一致 (這裡防止釣魚網站)、檢查是否過期、檢查是否被吊銷等,如果檢查都透過則證書受信任,則瀏覽器欄裡面會顯示一個小鎖頭,否則會給出證書不受信的提示。

    • 如果證書受信任,或者是使用者接受了不受信的證書,瀏覽器會生成一串隨機數,然後把隨機數、編碼變更通知(表示隨後的通訊都使用雙方商定的協議版本以及加密演算法)和客戶端握手結束通知傳送給伺服器

  4. 服務端接收瀏覽器發來的資料之後要做以下的操作:

    • 這時候服務端會有3個隨機數,2個是客戶端發來的,一個是服務端自己產生的,用著三個隨機數並結合對稱加密演算法生成“會話密碼”

    • 生成編碼變更通知、服務端握手結束通知

    • 使用商定好的HASH演算法對會話密碼、編碼變更通知、握手結束通知計算摘要,然後使用自己的私鑰進行對摘要進行簽名,最後使用客戶端公鑰加密資訊併傳送給客戶端

  5. 瀏覽器解密,然後得到訊息的HASH,如果與服務端發來的HASH一致,此時握手過程結束,之後所有的通訊資料都使用得到的“會話密碼” 加密。

這裡為什麼在認證透過後的資料傳輸使用認證過程產生的隨機密碼呢?這是因為使用對稱加密解密效能要比非對稱的高,尤其是對服務端的CPU壓力比較小,但是如果使用一個長期固定的對稱密碼就很不安全而隨機生成的就會有一個如何告訴通訊雙方且傳遞過程中不被竊取的問題所以就使用非對稱加密方式這樣不但保證了隨機密碼的安全同時也可以驗證服務端身份的真實性。

為什麼會產生這麼多隨機數呢?為了避免計算機上產生的隨機數不是真的隨機數,所以雙方都產生隨機數然後使用大家的隨機數來生成密碼。

相關文章