密碼學系列之:線上證書狀態協定OCSP詳解

2022-07-06 21:00:22

簡介

我們在進行網頁存取的時候會跟各種各樣的證書打交道,比如在存取https網頁的時候,需要檢測https網站的證書有效性。

OCSP就是一種校驗協定,用於獲取X.509數位憑證的復原狀態。它是為了替換CRL而出現的。

本文將會詳細介紹OCSP的實現和優點。

PKI中的CRL

我們知道在PKI架構中,CA證書是非常重要的元件,使用者端通過CA證書來驗證服務的可靠性。對於CA證書本身來說在建立的時候是可以指定過期時間的。這樣證書在過期之後就不可以使用,需要申請新的證書。

但是隻給證書指定過期時間是不夠的,比如我們因為業務的需求,需要復原證書怎麼辦呢?

PKI中提供了一個叫做CRL(certificate revocation list)的機制,用來維持被廢除的證書列表。

這個CRL是由CA來頒發的,一般是在證書過期之前生成的。因為如果證書已經過期了,那麼這個CRL是無意義的。

對於CRL本身來說,它是一個證書列表,裡面證書的格式通常也使用的是X.509。

CRL一般是由釋出證書的CA來維護和釋出的,釋出CRL的元件叫做CRL issuer,通常來說CRL issuer和CA是同一個服務,但是你也可以根據需要將CRL issuer和CA進行拆分。

CRL是由CA定時來發布的,當然你也可以按照需要在需要復原某個CA證書的時候重新發布CRL。所有的CRL都有過期時間,在這個過期時間之內,使用者端可以根據CRL中的簽名,去CA驗證CRL的有效性,從而防止CRL的偽造。

CRL的缺點

那麼CRL有什麼缺點呢?

首先CRL維持的是一個復原的證書列表,為了保證系統的有效性,使用者端在每次校驗CA證書有效性的時候,都需要從CA伺服器中獲取這個CRL。然後通過CRL來校驗對應的CA證書狀態。

如果每次都去拿這個CRL,就有可能會有下面幾個問題。

第一個問題是,如果CRL不可用,那麼使用者端就拿不到這個CRL,也就無法校驗CA證書的狀態,從而造成服務不可用。

另外一個問題是,如果要復原的證書比較多的話,這個CRL可能會比較大,從而造成網路資源的浪費。

最後一個問題是PKI證書體系本身的目的是建立一個可以自我校驗的,不依賴於線上服務的安全體系,如果每次都要線上獲取CRL的話,就是去了PKI的這一優勢。

CRL的狀態

雖然CRL維持的是一個復原證書列表,但是這個列表中證書的狀態還是有所不同的。

CRL中證書的狀態有兩種,第一種就是證書已經被複原了,比如證書的頒發機構CA發現之前的頒佈的證書是錯誤的,或者因為其他的原因如私鑰洩露導致原來的證書不夠安全,需要將證書撤回。或者證書機構因為未遵守某些策略導致證書被吊銷等,都需要將之前的證書設定為復原狀態。

還有一種狀態是一個臨時復原的狀態,這裡叫做Hold狀態,它表示證書暫時是無效的,比如在使用者沒有確定私鑰是否丟失的情況下。當用戶最終找回了私鑰,則這個證書還是可以被恢復的。

OCSP的工作流程

既然CRL有這麼多缺點,所以一個用來替代CRL的OCSP協定出現了。

我們先來看一下OCSP的工作流程。

假如A和B要進行使用PKI進行通訊。為了保證通訊的安全性,A將自己的公鑰發給B,並告訴B,這是我的公鑰,你可以用這個公鑰來校驗我傳送給你的訊息。

B在收到A的公鑰之後,並不能確定A的公鑰就是正確的,沒有被篡改的。於是從A的公鑰中提取出serial number,並將其封裝到一個'OCSP request'中發給CA伺服器。

CA伺服器中的OCSP responder讀取到了'OCSP request'請求,並從中提取出A的公鑰的serial number。OCSP responder從CA伺服器的資料庫中查詢這個serial number是否在這個資料庫被複原的列表中。

如果發現不在,那麼意味著A的公鑰仍然是有效的,OCSP responder將會傳送一個簽名後的OCSP response給B。

B通過使用CA伺服器的公鑰驗證OCSP response的有效性,從而確認A的公鑰仍然有效 。

最後B使用A的公鑰和A進行通訊。

OCSP的優點

從上面的OCSP的工作流程我們可以大概總結出下面幾個OCSP相對於CRL的優點。

首先OCSP響應的資料量要比CRL要小,所以對網路的要求和壓力更少。

另外因為OCSP響應要解析的資料更少,所以OCSP使用者端的實現要比CRL更加簡單。

雖然因為CRL的各種缺點,在web環境中已經不再被使用,而是被更加高效的OCSP替換,但是CRL仍然被執行在CA的其他環境中。

OCSP協定的細節

OCSP協定是在RFC 6960中定義的。

OCSP協定可以分為請求協定和響應協定兩部分,接下來分別來進行介紹。

OCSP請求

一個OCSP請求需要包含協定版本號,請求服務,要校驗的證書identifier和可選的擴充套件部分。

OCSP responder在接收到OCSP的請求之後,會去校驗OCSP訊息的有效性,如果訊息有問題則會返回異常,否則的話會根據請求的服務進行處理。

OCSP請求如果用ASN.1(Abstract Syntax Notation One)抽象語法標記這可以如下表示:

   OCSPRequest     ::=     SEQUENCE {
       tbsRequest                  TBSRequest,
       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }

   TBSRequest      ::=     SEQUENCE {
       version             [0]     EXPLICIT Version DEFAULT v1,
       requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
       requestList                 SEQUENCE OF Request,
       requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
          Signature       ::=     SEQUENCE {
            signatureAlgorithm      AlgorithmIdentifier,
            signature               BIT STRING,
            certs               [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}

   Version         ::=             INTEGER  {  v1(0) }

   Request         ::=     SEQUENCE {
       reqCert                     CertID,
       singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }

   CertID          ::=     SEQUENCE {
       hashAlgorithm       AlgorithmIdentifier,
       issuerNameHash      OCTET STRING, -- Hash of issuer's DN
       issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
       serialNumber        CertificateSerialNumber }

ASN.1是一個介面描述語言,通過ASN.1,我們可以很清晰的描述資料的格式資訊。

一個OCSPRequest是由可選擇簽名的OCSP請求tbsRequest和對應的簽名optionalSignature組成的。

其中TBSRequest中包含了版本號,OCSP requestor的名字,證書的狀態列表requestList,可選的擴充套件資料這幾項組成的。

OCSP響應

對於OCSP的響應來說,根據傳輸協定的不同它的結構也是不同的。但是所有的響應都應該包含responseStatus欄位表示請求的處理狀態。

OCSP響應用ASN.1格式來表示如下所示:

   OCSPResponse ::= SEQUENCE {
      responseStatus         OCSPResponseStatus,
      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }

   OCSPResponseStatus ::= ENUMERATED {
       successful            (0),  -- Response has valid confirmations
       malformedRequest      (1),  -- Illegal confirmation request
       internalError         (2),  -- Internal error in issuer
       tryLater              (3),  -- Try again later
                                   -- (4) is not used
       sigRequired           (5),  -- Must sign the request
       unauthorized          (6)   -- Request unauthorized
   }

      ResponseBytes ::=       SEQUENCE {
       responseType   OBJECT IDENTIFIER,
       response       OCTET STRING }

responseStatus是響應的狀態,responseBytes是可選的響應結果。

這裡的response是一個BasicOCSPResponse物件的DER編碼:

   BasicOCSPResponse       ::= SEQUENCE {
      tbsResponseData      ResponseData,
      signatureAlgorithm   AlgorithmIdentifier,
      signature            BIT STRING,
      certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }

OCSP stapling

可以看到OCSP需要客戶在需要檢視證書是否被吊銷的時候,需要向OCSP responser請求,以確認證書的有效性。

但是這種方式實際上洩露了使用者的隱私資訊,因為OCSP responser知道了使用者端需要校驗的證書,就知道使用者端正在存取的網站。

於是引入了OCSP stapling來解決這個問題。

那麼什麼是OCSP stapling呢?

OCSP stapling是直接將OCSP證書放到使用者端要存取的web伺服器上,因為OCSP證書是新增了時間戳和數位簽章的,所以可以保證其正確性。

這些OCSP證書會在使用者端和web端建立SSL 握手的時候就包含在OCSP響應中。

這樣使用者端不需要單獨和CA建立額外的連線,從而提高了效能。

OCSP stapling需要在伺服器端主動開啟。

如果你用的是apache伺服器,首先需要版本大於2.3.3。

然後需要在.conf檔案中的<VirtualHost></VirtualHost> block外部新增:

SSLStaplingCahe shmcb: /tmp/stapling_cache(128000)

然後在<VirtualHost></VirtualHost> block的內部新增:

SSLUseStapling On

如果你用的是nginx,首先需要版本大於1.3.7。

然後在nginx的組態檔server {} block中新增:

ssl_stapling on;
ssl_stapling_verify on;

如果你想驗證一個網站是否開啟了OCSP stapling,可以到https://entrust.ssllabs.com/網站中進行查詢:

在這個網站中,你可以輸入任何要查詢的網站地址,然後可以得到下面的資訊:

可以看到這個網站是開啟了OCSP stapling的。

總結

OCSP和OCSP stapling是非常有用的證書復原校驗協定,已經被廣泛的使用。大家可以檢查一下自己的網站有沒有用到哦。

更多內容請參考 http://www.flydean.com/43-pki-ocsp/

最通俗的解讀,最深刻的乾貨,最簡潔的教學,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!