HTTP摘要认证

**摘要訪問認證**是一種協議規定的 Web 伺服器用來同網頁瀏覽器進行認證信息協商的方法。它在密碼發出前，先對其應用哈希函數，這相對於 HTTP 基本認證發送明文而言，更安全。

從技術上講，摘要認證是使用隨機數來阻止進行密碼分析的 MD5 加密哈希函數應用。它使用 HTTP 協議。

## 概述

摘要訪問認證最初由 RFC 2069 (_HTTP 的一個擴展：摘要訪問認證_) 中被定義。RFC 2069 大致定義了一個傳統的由伺服器生成隨機數來維護安全性的摘要認證架構。認證響應由下列組成（HA1、HA2、A1、及 A2 為字符串變量的名稱）：

　
: $\mathrm {HA1} =\mathrm {MD5} {\Big (}\mathrm {A1} {\Big )}=\mathrm {MD5} {\Big (}\mathrm {username} :\mathrm {realm} :\mathrm {password} {\Big )}$

　
: $\mathrm {HA2} =\mathrm {MD5} {\Big (}\mathrm {A2} {\Big )}=\mathrm {MD5} {\Big (}\mathrm {method} :\mathrm {digestURI} {\Big )}$

　
: $\mathrm {response} =\mathrm {MD5} {\Big (}\mathrm {HA1} :\mathrm {nonce} :\mathrm {HA2} {\Big )}$

RFC 2069 隨後被 RFC 2617 (_HTTP 認證：基本及摘要訪問認證_) 取代。RFC 2617 引入了一系列安全增強的選項；「保護質量」(qop)、隨機數計數器由客戶端增加、以及客戶生成的隨機數。這些增強為了防止如選擇明文攻擊的密碼分析。

　
: $\mathrm {HA1} =\mathrm {MD5} {\Big (}\mathrm {A1} {\Big )}=\mathrm {MD5} {\Big (}\mathrm {username} :\mathrm {realm} :\mathrm {password} {\Big )}$

如果 qop 值為「auth」或未指定，那麼 HA2 為

　
: $\mathrm {HA2} =\mathrm {MD5} {\Big (}\mathrm {A2} {\Big )}=\mathrm {MD5} {\Big (}\mathrm {method} :\mathrm {digestURI} {\Big )}$

如果 qop 值為「auth-int」，那麼 HA2 為

　
: $\mathrm {HA2} =\mathrm {MD5} {\Big (}\mathrm {A2} {\Big )}=\mathrm {MD5} {\Big (}\mathrm {method} :\mathrm {digestURI} :\mathrm {MD5} (entityBody){\Big )}$

如果 qop 值為「auth」或「auth-int」，那麼如下計算 response：

　
: $\mathrm {response} =\mathrm {MD5} {\Big (}\mathrm {HA1} :\mathrm {nonce} :\mathrm {nonceCount} :\mathrm {clientNonce} :\mathrm {qop} :\mathrm {HA2} {\Big )}$

如果 qop 未指定，那麼如下計算 response：

　
: $\mathrm {response} =\mathrm {MD5} {\Big (}\mathrm {HA1} :\mathrm {nonce} :\mathrm {HA2} {\Big )}$

上面所述的這種當 qop 未指定的情況，也就是遵循簡化的 RFC 2069 標準。

## MD5 安全問題對摘要認證的影響

在 HTTP 摘要認證中使用 MD5 加密是為了達成 "不可逆的"，也就是說，當輸出已知的時候，確定原始的輸入應該是相當困難的。如果密碼本身太過簡單，也許可以通過嘗試所有可能的輸入來找到對應的輸出（窮舉攻擊），甚至可以通過字典或者適當的查找表加快查找速度。

HTTP 構架由 Phillip Hallam-Baker 於 1993 年在 CERN 設計成的，並且沒有吸收後續認證系統的改進，如基於密鑰的雜湊訊息驗證碼 HMAC 的發展。雖然所使用的密碼結構是基於 MD5 雜湊函數的，在 2004 年，通常認為衝突攻擊不會影響明文（如密碼）未被得知的應用。
但是，在 2006 年的聲明 (Kim, Biryukov2, Preneel, Hong, "On the Security of HMAC and NMAC Based on HAVAL MD4 MD5 SHA-0 and SHA-1") 導致了一些包括關於 MD5 應用的疑慮。不過，至今為止，MD5 衝突攻擊沒有被視為對摘要認證的威脅，並且 RFC 2617 允許伺服器實現一些機制來檢測衝突以及重放攻擊。

## HTTP 摘要認證的考慮

### 優勢

HTTP 摘要認證目的在於比傳統摘要認證構架更安全；例如，「明顯強於（如）CRAM-MD5……」。 （RFC 2617）

一些 HTTP 摘要認證的安全性增強如下：

* 密碼並非直接在摘要中使用，而是 HA1 = MD5 (username:realm:password)。這就允許一些實現（如，JBoss DIGESTAuth（頁面存檔備份，存於網際網路檔案館）) 僅存儲 HA1 而不是明文密碼。
* 在 RFC 2617 中引入了客戶端隨機數 nonce（cnonce），這將使客戶端能夠防止選擇明文攻擊，否則像彩虹表（Rainbow table）這類東西就會成為摘要認證構架的威脅。
* 伺服器隨機數 nonce 允許包含時間戳。因此伺服器可以檢查客戶端提交的隨機數 nonce，以防止重放攻擊。
* 伺服器也可以維護一個最近發出或使用過的伺服器隨機數 nonce 的列表以防止重用。

### 劣勢

摘要訪問認證有意成為一個安全性的折衷。它意圖代替非加密的 HTTP 基本認證。但是，它沒有被設計為替換強認證協議，例如公鑰密碼學或 Kerberos 認證。

在安全性方面，摘要訪問認證有幾個缺點：

* RFC 2617 中的許多安全選項都是可選的。如果伺服器沒有指定保護質量 (qop)，客戶端將以降低安全性的早期的 RFC 2069 的模式操作。
* 摘要訪問認證容易受到中間人攻擊。舉例而言，一個中間人攻擊者可以告知客戶端使用基本訪問認證或早期的 RFC 2069 摘要訪問認證模式。進一步而言，摘要訪問認證沒有提供任何機制幫助客戶端驗證伺服器的身份。
* 一些伺服器要求密碼以可逆加密算法存儲。但是，僅存儲用戶名、realm、和密碼的摘要是可能的。
* 它阻止了使用強密碼哈希函數（如 bcrypt）保存密碼（因為無論是密碼、或者用戶名、realm、密碼的摘要都要求是可恢復的）。

### 可替代的認證協議

一些可以用於 Web 應用程式的強認證協議包括：

* 公鑰密碼學認證（通常隨 HTTPS / SSL 客戶端整數一起實現）。
* Kerberos 或 SPNEGO 認證，主要是在配置為 Integrated Windows Authentication (IWA) 的微軟的 IIS 使用。
* Secure Remote Password protocol (適用於 HTTPS / TLS 層)。

常用的弱明文協議：

* HTTP 基本認證構架
* HTTP+HTML 表單認證

使用 HTTPS 網絡加密同時使用這些弱明文協議解決了許多摘要訪問認證試圖要防止的許多威脅。

## 示例及說明

下面的例子出自 RFC 2617，在這裡進行了擴展，對每一個請求和響應顯示出完整的文本。注意，這裡僅僅涵蓋了「auth」保護質量的代碼，因為在撰寫期間，所知道的只有 Opera 和 Konqueror 網頁瀏覽器支持「auth-int」（帶完整性保護的認證）。雖然定義中提到了 HTTP 1.1，但是該構架可以像下面所描述的這樣添加到 1.0 的伺服器中去。

典型的認證過程包括如下步驟。

* 客戶端請求一個需要認證的頁面，但是不提供用戶名和密碼。通常這是由於用戶簡單的輸入了一個地址或者在頁面中點擊了某個超連結。
* 伺服器返回 401 "Unauthorized" 響應代碼，並提供認證域 (realm)，以及一個隨機生成的、只使用一次的數值，稱為密碼隨機數 nonce。
* 此時，瀏覽器會向用戶提示認證域 (realm)（通常是所訪問的計算機或系統的描述），並且提示用戶名和密碼。用戶此時可以選擇取消。
* 一旦提供了用戶名和密碼，客戶端會重新發送同樣的請求，但是添加了一個認證頭包括了響應代碼。
* 在這個例子中，伺服器接受了認證並且返回了請求頁面。如果用戶名非法和 / 或密碼不正確，伺服器將返回 "401" 響應代碼，然後客戶端會再次提示用戶輸入用戶名及密碼。

注意：客戶端可能已經擁有了用戶名和密碼，因此不需要提示用戶，比如以前存儲在瀏覽器里的。

---

**客戶端請求 (無認證)**
:

```
GET /dir/index.html HTTP/1.0
Host: localhost
```

(跟隨一個新行，形式為一個回車再跟一個換行）

**伺服器響應**
:

```
HTTP/1.0 401 Unauthorized
Server: HTTPd/0.9
Date: Sun, 10 Apr 2005 20:26:47 GMT
WWW-Authenticate: Digest realm="testrealm@host.com",
                        qop="auth,auth-int",
                        nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                        opaque="5ccc069c403ebaf9f0171e9517f40e41"
Content-Type: text/html
Content-Length: 311

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd（頁面存檔備份，存於網際網路檔案館）">
<HTML>
  <HEAD>
    <TITLE>Error</TITLE>
    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
  </HEAD>
  <BODY><H1>401 Unauthorized.</H1></BODY>
</HTML>
```

**客戶端請求 (用戶名 "Mufasa", 密碼 "Circle Of Life")**
:

```
GET /dir/index.html HTTP/1.0
Host: localhost
Authorization: Digest username="Mufasa",
                     realm="testrealm@host.com",
                     nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                     uri="/dir/index.html",
                     qop=auth,
                     nc=00000001,
                     cnonce="0a4f113b",
                     response="6629fae49393a05397450978507c4ef1",
                     opaque="5ccc069c403ebaf9f0171e9517f40e41"
```

(跟隨一個新行，形式如前所述).

**伺服器響應**
:

```
HTTP/1.0 200 OK
Server: HTTPd/0.9
Date: Sun, 10 Apr 2005 20:27:03 GMT
Content-Type: text/html
Content-Length: 7984
```

(隨後是一個空行，然後是所請求受限制的 HTML 頁面).

---

如下所述，response 值由三步計算而成。當多個數值合併的時候，使用冒號作為分割符。

1. 對用戶名、認證域 (realm) 以及密碼的合併值計算 MD5 哈希值，結果稱為 HA1。
2. 對 HTTP 方法以及 URI 的摘要的合併值計算 MD5 哈希值，例如，`"GET"` 和 `"/dir/index.html"`，結果稱為 HA2。
3. 對 HA1、伺服器密碼隨機數 (nonce)、請求計數 (nc)、客戶端密碼隨機數 (cnonce)、保護質量 (qop) 以及 HA2 的合併值計算 MD5 哈希值。結果即為客戶端提供的 response 值。

因為伺服器擁有與客戶端同樣的信息，因此伺服器可以進行同樣的計算，以驗證客戶端提交的 response 值的正確性。在上面給出的例子中，結果是如下計算的。
（`MD5()` 表示用於計算 MD5 哈希值的函數；「\」表示接下一行；引號並不參與計算）

完成 RFC 2617 中所給出的示例，將在每步得出如下結果。

```
   HA1 = MD5( "Mufasa:testrealm@host.com:Circle Of Life" )
       = 939e7578ed9e3c518a452acee763bce9

   HA2 = MD5( "GET:/dir/index.html" )
       = 39aff3a2bab6126f332b942af96d3366

   Response = MD5( "939e7578ed9e3c518a452acee763bce9:\
                    dcd98b7102dd2f0e8b11d0f600bfb0c093:\
                    00000001:0a4f113b:auth:\
                    39aff3a2bab6126f332b942af96d3366" )
            = 6629fae49393a05397450978507c4ef1
```

此時客戶端可以提交一個新的請求，重複使用伺服器密碼隨機數 (nonce)（伺服器僅在每次「401」響應後發行新的 nonce），但是提供新的客戶端密碼隨機數 (cnonce)。在後續的請求中，十六進位請求計數器 (nc) 必須比前一次使用的時候要大，否則攻擊者可以簡單的使用同樣的認證信息重放老的請求。由伺服器來確保在每個發出的密碼隨機數 nonce 時，計數器是在增加的，並拒絕掉任何錯誤的請求。顯然，改變 HTTP 方法和 / 或計數器數值都會導致不同的 response 值。

伺服器應當記住最近所生成的伺服器密碼隨機數 nonce 的值。也可以在發行每一個密碼隨機數 nonce 後，記住過一段時間讓它們過期。如果客戶端使用了一個過期的值，伺服器應該響應「401」狀態號，並且在認證頭中添加 `stale=TRUE`，表明客戶端應當使用新提供的伺服器密碼隨機數 nonce 重發請求，而不必提示用戶其它用戶名和口令。

伺服器不需要保存任何過期的密碼隨機數，它可以簡單的認為所有不認識的數值都是過期的。伺服器也可以只允許每一個伺服器密碼隨機數 nonce 使用一次，當然，這樣就會迫使客戶端在發送每個請求的時候重複認證過程。需要注意的是，在生成後立刻過期伺服器密碼隨機數 nonce 是不行的，因為客戶端將沒有任何機會來使用這個 nonce。

## SIP 摘要認證

SIP 基本上使用了同樣的摘要認證算法。它由 RFC 3261 定義。

## 瀏覽器實現

大多數瀏覽器都基本上實現了該協議，除了某些特性，比如檢查 auth-int、或者 MD5-sess 算法。如果伺服器要求處理這類可選特性，客戶端可能無法進行認證（雖然需要注意的是，Apache 伺服器的 mod\_auth\_digest 模塊也沒有完全實現 RFC 2617）。

* Amaya
* 基於 Gecko: (不包括 auth-int: [1])
  * Mozilla Application Suite
  * Mozilla Firefox
  * Netscape 7+
* iCab 3.0.3+
* 基於 KHTML- 及 WebKit: (不包括 auth-int [2]（頁面存檔備份，存於網際網路檔案館）)
  * iCab 4
  * Konqueror
  * Google Chrome
  * Safari
* 基於 Tasman:
  * Internet Explorer for Mac
* Trident-based:
  * Internet Explorer 7+ (不包括 auth-int)
* 基於 Presto:
  * Opera
  * Opera Mobile
  * Opera Mini
  * Nintendo DS 瀏覽器
  * Nokia 770 瀏覽器
  * Sony Mylo 1 的瀏覽器
  * Wii Internet Channel 瀏覽器

## 參見

* 認證和密鑰協商協議
* HTTP 基本認證

## 參考

## 外部連結

* RFC 2617
* RFC 2069 (廢棄的)