使用SHA256算法做HTTP摘要認證
HTTP的認證分為兩種,basic和digest,兩種方法目前網上都有介紹,不過大家常用的還是digest認證,相比於basic而言,安全性還是要高一點的。不過digest認證目前在網上看到的資料都是針對RFC2617的,描述的都是MD5摘要算法,但是對於有些需求(比如客戶要求更高的安全性,比如在某些公司直接就不讓用MD5),這個時候MD5就不適用了,這種情況SHA算法就派上用場了,幸運的是RFC也出了這一標准RFC7616(the MD5 algorithm is still supported
but NOT RECOMMENDED.),我這邊就簡單描述一下SHA256在digest認證過程中的應用。
注:目前時間原因,沒有親自實操,只是看了點資料,這篇博客目前主要是對RFC7616做個解釋,日后還要自己敲代碼做驗證,目前只能做參考,詳細的摘要認證可以參考HTTP摘要認證。
HTTP摘要認證流程
- 客戶端請求
- 服務器回應
- 客戶端重新請求並附帶Authorization域
- 服務器根據報頭信息和數據信息進行認證
1,客戶端請求
首先客戶端發送request到服務器,這個request可以是一個對象訪問,比如get一篇博客,也可以是一個軟件自定義的功能請求,比如開發就定義這是個注冊請求,收到這個請求就要做注冊認證。
2,服務器回應
RFC定義的是,當服務器收到一個要對access-protected對象進行訪問的request時,request若無Authorization header則服務器回應客戶端401 Unauthorized狀態碼,並附帶WWW-Authorization header。大致可能是這樣的:
HTTP /1.1 401 Unauthorized
WWW-Authenticate:Digest
realm= ”test realm”
qop=auth,auth-int”
nonce=”66C4EF58DA7CB956BD04233FBB64E0A4”
事實上server的動作要怎么操作看開發自己定義(比如收到特定請求也回應401),但是要遵循標准。WWW-Authorization回應定義了摘要認證的整個scheme,它包含了許多字段,我就主要介紹幾個:
realm: A string to be displayed to users so they know which username and password to use.
一般應該是這樣的 "registered_users@example.com"。
nonce: A server-specified string which should be uniquely generated each time a 401 response is made. 就是server產生的一個隨機數,一般可以根據時間戳來做這個。
algorithm: A string indicating an algorithm used to produce the digest and an unkeyed digest. 表明此次認證的摘要算法,如果沒有,則默認使用MD5。
In this document, the string obtained by applying the digest
algorithm to the data "data" with secret "secret" will be denoted
by KD(secret, data), and the string obtained by applying the
unkeyed digest algorithm to the data "data" will be denoted
H(data). KD stands for Keyed Digest, and the notation unq(X)
means the value of the quoted-string X without the surrounding
quotes and with quoting slashes removed.
For "<algorithm>" and "<algorithm>-sess"
H(data) = <algorithm>(data)
and
KD(secret, data) = H(concat(secret, ":", data))
For example:
For the "SHA-256" and "SHA-256-sess" algorithms
H(data) = SHA-256(data)
后面的這點中文實在不好解釋。。。
qop: This parameter MUST be used by all implementations. It is a
quoted string of one or more tokens indicating the "quality of
protection" values supported by the server. The value "auth"
indicates authentication; the value "auth-int" indicates
authentication with integrity protection. See the descriptions
below for calculating the response parameter value for the
application of this choice. Unrecognized options MUST be ignored.
3,客戶端重新請求並且附帶Authorization域
客戶端收到401后,如果客戶端是瀏覽器,則會彈出對話框,讓用戶輸入用戶名和密碼,然后發送新的請求到服務器,不過此時請求中就帶有Authorization header了。Authorization也有許多字段,這里也主要介紹其中的幾個:
response: 計算出來的一個字符串,后面認證要用,如何計算的后面介紹。
username: 字符串表明當前用戶名。
realm: 同上。
qop: 第二步中服務器回應中的WWW-Authorization中的qop中的一個。
cnonce: This parameter MUST be used by all implementations. The cnonce
value is an opaque quoted ASCII-only string value provided by the
client and used by both client and server to avoid chosen
plaintext attacks, to provide mutual authentication, and to
provide some message integrity protection. See the descriptions
below of the calculation of the rspauth and response values.
response的計算:
如果qop是auth或者auth-int:
response=<">(KD(H(A1),unq(nonce)":"nc":"unq(cnonce)":"unq(qop)":"H(A2))<">
當采用SHA256算法時,A1 = unq(username)":"unq(realm)":"passwd passwd是該用戶的密碼。
如果qop是auth或者沒有定義,則A2=Method":"request-uri,如果qop是auth-int,則A2=Method":"request-uri":"H(entity-body)
4,服務器根據報頭信息和數據信息進行認證
服務器收到了客戶端的帶有Authorization域的請求,則查找該username的密碼,然后重新按照第三步的規則計算一遍response,然后和Authorization域中的response進行對比,如果一樣,則認證成功,否則失敗。
大致流程大概如上所示,不過寫的非常簡陋,還是強烈建議看RFC文檔,標准定義其實寫的非常詳細。
