HTTP Digest Access Authentication Schema

HTTP Digest Access Authentication Schema

背景

随着年龄的增长,很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来,技术出身的人总是很难放下一些执念,遂将这些知识整理成文,以纪念曾经努力学习奋斗的日子。本文内容并非完全原创,大多是参考其他文章资料整理所得,感谢每位技术人的开源精神。

介绍

HTTP Digest Access Authentication Schema,HTTP 摘要访问认证模式,是 HTTP 1.1 引入的替代 HTTP Basic Access Authentication Schema 的方案,为了解决 HTTP Basic Access Authentication Schema 中存在的安全问题:通过网络传输未加密的用户ID和密码

HTTP Digest 同 HTTP Basic 一样,基于 challenge-response 认证机制实现身份认证方案,不同之处在于,HTTP Digest 不会直接发送明文密码,而是采用 checksum 检验方式对请求进行验证。

HTTP Digest Access Authentication 中的 challenge 使用一个 nonce 值,一个有效的 response 包含的 checksum用户ID密码nonceHTTP请求方法HTTP请求URI 通过算法生成(默认 MD5),这样就永远不会以明文方式发送密码。

Challenge

服务器发送的 challengeDigest digest-challenge,其中 Digest 指明服务器需要的访问认证方式,digest-challenge 格式如下:

复制代码
realm | [domain] | nonce | [opaque] | [stale] | [algorithm] | [qop-options] | [auth-param]

其中 realmnonce 这两个字段是必须的。字段说明:

  • realm:一个标识受保护资源的字符串,指示用户应该使用哪个用户ID和密码进行认证。此字符串至少应该包含执行认证的主机名称,还可以另外指示哪些用户集合可能具有访问权限,如:registered_users@somehost
  • domain: 授权访问的URI列表,每项之间以空格符分隔。
  • nonce:服务器每次返回 401 Unauthorized 时生成的唯一随机数,通常推荐使用 Base64 编码或十六进制数,实际依赖于服务器的具体实现。服务器向客户端发送 challenge 时会附带一个 nonce 随机数,客户端返回的 response 中摘要值计算会用到此 nonce 值。nonce 的存在增加了破解密码的难度,防范了 中间人恶意服务器 等攻击类型。RFC 2617建议生成随机数的计算公式:nonce=Base64(timestamp MD5(timestamp:ETag:private-key))
  • opaque:服务器指定的一个数字字符串,客户端后续发送的对相同域(realm )的访问请求中,HTTP Headers 的 Authorization 应带有此值(保持不变),通常推荐使用 Base64 编码或十六进制数据。
  • stale:一个标识,表明客户端的上一请求中使用了过期的 nonce 值。如果为 TRUE 则提示客户端使用新的加密 response 值重试请求。只有当服务器收到一个 nonce 过期的请求,但该 nonce 有一个有效的摘要(表明客户端知道正确的用户ID和密码)时,服务器才应该将 stale 设置为 TRUE
  • algorithm:一个字符串,指明生成摘要和校验和(checksum)的算法,如果没有设置则默认采用 MD5。
  • qop:quality of protection,质量保护,包含 authauth-int 两种策略,默认 authauth-int 增加了报文完整性检测。
  • auth-param:为未来扩展保留。

Response

客户端发送的 responseDigest digest-response,其中 Digest 指明客户端遵从的访问认证方式,digest-response 格式如下:

复制代码
username | realm | nonce | digest-uri | response | [algorithm] | [cnonce] | [opaque] | [message-qop] | [nonce-count] | [auth-param]

字段说明:

  • username:用于特定域(realm)认证的用户ID。
  • digest-uri:请求的相对URI,因为代理在传输过程中可能修改请求,所以此处重复说明。
  • response:摘要,是由32位十六进制数字组成的字符串,证明客户端知道密码。
  • qop:同 challengeqop 用途一致,必须是服务器发送的 challenge 中指明支持的 qop 之一,此值会影响摘要计算。
  • cnonce:客户端随机数,使得双方都可以查验对方的身份,并对消息的完整性提供一些保护。
  • ncnonce 计数器,是一个十六进制的数值,表示同一 nonce 下客户端发送出请求的数量,在第一个 response 请求中 nc=00000001,目的是让服务器保持这个计数器的一个副本,以便检测重复的请求。
  • auth-param:为未来扩展保留。

摘要计算

response 的值由三步计算而成,使用冒号作为分隔符合并多个数值:

  1. 对用户ID、域(realm )及密码的合并值计算MD5哈希,结果称为 HA1(安全相关)。

    • 如果算法是 MD5 ,则 A1=<userid>:<realm>:<password>

    • 如果算法是 MD5-sess ,则 A1=MD5(<user>:<realm>:<password>):<nonce>:<cnonce>

      HA1 = MD5(A1) = MD5(username:realm:password)

  2. 对 HTTP 方法以及 URI 的摘要的合并值计算 MD5 哈希,如 GET/dir/index.html,结果称为 HA2(报文相关)。A2 表示是与报文自身相关的信息,比如 URL,A2 加入摘要计算的主要目的是有助于防止反复。

    • qop 为指定或指定为 auth,则 A2=<request-method>:<uri-directive-value>

      HA2 = MD5(A2) = MD5(method:digestURI)

    • qop 指定为 auth-int,则 A2=<request-method>:<uri-directive-value>:MD5(<request-entity-body>)

      HA2 = MD5(A2) = MD5(method:digestURI:MD5(entityBody))

  3. HA1noncenccnonceqop 以及 HA2 的合并值计算 MD5 哈希,结果即为客户端提供的 response 值,计算规则:

    • qop 没有指定,则 response = MD5(HA1:nonce:HA2)
    • qop 指定为 authauth-int,则 response = MD5(HA1:nonce:nonceCount:clientNonce:qop:HA2)

流程

  1. 客户端请求访问受保护资源;

  2. 服务端接收到请求后,在请求头部(HTTP Request Headers)中未找到 Authorization,返回 401 Unauthorized,返回响应头(HTTP Response Headers)中带有 WWW-Authenticate

    复制代码
    WWW-Authenticate: Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"
  3. 客户端收到服务器响应后,使用 用户ID密码nonceHTTP请求方法HTTP请求URI,通过指定算法(如默认的 MD5 )计算生成一个摘要,将此摘要与认证请求一起发送给服务器进行认证。客户端发送的认证请求中包含 Authorization 头信息,格式如下:

    复制代码
    Authorization: Digest username="Mufasa", realm="testrealm@host.com", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", uri="/dir/index.html", qop=auth, nc=00000001, cnonce="0a4f113b", response="6629fae49393a05397450978507c4ef1", opaque="5ccc069c403ebaf9f0171e9517f40e41"

    其中 response 的计算过程:

    复制代码
    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
  4. 服务器收到客户端的认证请求后,使用存储的密码和发送的参数计算摘要,如果与客户端发送的摘要匹配则认证成功。成功认证后,服务器可以返回 Authentication-Info 响应头,格式:

    复制代码
    Authentication-Info: nextnonce | [message-qop] | [response-auth] | [cnonce] | [nonce-count]

    字段说明:

    • nextnonce:如果服务器返回 nextnonce,则客户端下次请求的头信息中 Authorizationnonce 需要设置为此值,否则可能导致服务器要求重新认证。
    • message-qop:服务器应用与响应的 qopauth 表示认证,auth-int 表示完整性认证保护,应该与对应的客户端请求中 qop 值一致。
    • response-auth:支持双向身份认证,即表明服务器知道用户的密码。
    • cnonce:同 responsecnonce
    • nonce-count:同 responsenc

注意:

  • 后续客户端可以提交新请求,重复使用服务器密码随机数(nonce),服务器仅在每次响应 401 Unauthorized 时发送新的 nonce
  • 后续请求中,十六进制请求计数器(nc)必须比前一次要大,否则攻击者可以使用同样的认证信息重放已有的请求。
  • 服务器应当记住最近生成的密码随机数(nonce),也可以为每一个密码随机数分配一个过期时间,如果客户端请求中携带的是过期的密码随机数,则服务器响应 401 Unauthorized,并在 digest-challenge 中添加 stale=TRUE,表明客户端应该使用新的密码随机数重发请求。

总结

HTTP Digest 相比于 HTTP Basic 的优势:

  • 不发送明文密码;
  • 使用随机数 nonce 防止重放攻击。

HTTP Digest 的缺陷:

  • 如果摘要数据被攻击者截获,密码可能会被离线破解;
  • 不提供消息完整性和机密性保护,最好配合 HTTPS 使用。

参考

RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication\](RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication)

相关推荐
灰子学技术9 小时前
Envoy HTTP 过滤器处理技术文档
网络·网络协议·http
时空自由民.13 小时前
HTTP协议和HTTPS协议结合天气获取案例介绍
网络协议·http·https
时空自由民.19 小时前
HTTP协议帧格式
网络·网络协议·http
Rust研习社1 天前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
灰子学技术1 天前
Envoy HTTP 流量层面的 Metric 指标分析
网络·网络协议·http
TimeAground1 天前
HTTP 协议全解:从报文到 HTTP/3,Android 开发者需要知道的一切
http
lifewange1 天前
如何设计一个 RESTful API
后端·http·restful
夜瞬2 天前
HTTP基础教程:请求方法、状态码、JSON、鉴权、超时、重试与流式返回
网络协议·http·json