HTTP Digest Access Authentication Schema

embedded/2024/9/25 7:25:50/

HTTP Digest Access Authentication Schema

  • 背景
  • 介绍
  • Challenge
  • Response
  • 摘要计算
  • 流程
  • 总结
  • 参考

背景

本文内容大多基于网上其他参考文章及资料整理后所得,并非原创,目的是为了需要时方便查看。

介绍

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)

流程

<a class=HTTP Digest Access Authentication Schema" />

  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)


http://www.ppmy.cn/embedded/44200.html

相关文章

oracle tree

select * from "Test"; INSERT INTO "Test" ("id", "name", "pid") VALUES (01, 中国, 00); INSERT INTO "Test" ("id", "name", "pid") VALUES (01.01, 福建, 01); INSERT INTO…

函数编程实际应用-异步任务

背景 常见的函数式接口&#xff0c;就是对函数编程的应用Runnable 没有返回值的函数式接口Callable 有返回值的函数式接口 使用线程池 一般来说&#xff0c;很少使用new Thread&#xff08;函数对象&#xff09;这种方式来直接 创建线程&#xff0c;更多的时候使用的线程成来集…

计算机网络基本概念

文章目录 情景带入一些基本概念网络网络编程&#xff1a;7层网络模型OSI&#xff1a;TCP/IP Protocol Architecture Layers与OSI的对应关系SocketClient-Server Application报文段&#xff1a;传输协议&#xff1a;Mac地址IP地址端口URL 情景带入 随着时代的发展&#xff0c;我…

永久代(Permanent Generation)和元空间(Metaspace)

永久代&#xff08;Permanent Generation&#xff09;和元空间&#xff08;Metaspace&#xff09;是Java虚拟机&#xff08;JVM&#xff09;内存管理中的两个概念&#xff0c;主要区别在于它们的实现方式和内存分配策略。 永久代&#xff08;Permanent Generation&#xff09;…

使用 Supabase 的 Realtime + Storage 非常方便呢

文章目录 &#xff08;一&#xff09;Supabase&#xff08;二&#xff09;Realtime&#xff08;消息&#xff09;&#xff08;2.1&#xff09;Python 消息订阅&#xff08;2.2&#xff09;JavaScript 消息订阅 &#xff08;三&#xff09;Storage&#xff08;存储&#xff09;&…

python规则表达式re模块:笔记0529

Python语言使用printf printf&#xff1a;https://blog.51cto.com/u_16099181/7758801 使用python进行自动化运维脚本编写时经常需要处理远程设备返回到控制字符&#xff0c;比如下面这个例子&#xff0c;控制字符在使用print进行调试输出时因为是非ascii字符不显示&#xff0…

Vue插槽solt如何传递具名插槽的数据给子组件?

在Vue中&#xff0c;你可以通过作用域插槽&#xff08;scoped slots&#xff09;来传递数据给子组件。这同样适用于具名插槽。首先&#xff0c;你需要在子组件中定义一个具名插槽&#xff0c;并通过v-slot指令传递数据。例如&#xff1a; 子组件&#xff08;ChildComponent.vu…

长安链使用Golang编写智能合约教程(二)

长安链2.3.0的go合约虚拟机和2.3.0以下的不兼容&#xff0c;编译的方式也有差异&#xff0c;所以在ide上做了区分。 教程三会写一些&#xff0c;其他比较常用SDK方法的解释和使用方法 教程一&#xff1a;&#xff08;长安链2.1.的版本的智能合约&#xff09; 教程三&#xff…