摘要

  • RFC 9345 允许终端证书的持有者签出一份范围很窄的 Delegated Credential。边缘持有对应私钥后,可以为支持该机制的 TLS/DTLS 1.3 对端完成 CertificateVerify;证书链与预期身份仍由客户端照常验证。
  • 委托凭据默认最长七天,但“短期”只是缩小损失窗口,不是单独的即时吊销通道。私钥一旦被复制,攻击者可用到该凭据到期;若不能等待,只能考虑吊销签发它的长期证书,影响面远大于一个边缘节点。
  • 完整证据必须把证书的主动许可、委托对象字节、签名操作、私钥来源、部署范围、客户端协商、握手接受、回退路径、会话恢复与到期后拒绝连在一起。一次成功握手既不能证明密钥只在预定边缘,也不能代替应用授权。

到底有什么越过了边界

把证书私钥留在后端,并不意味着前端永远要为每次握手回源签名。证书持有者可以签署一份委托凭据,把一个新的公钥、有效期和算法绑定到现有终端证书。边缘只要掌握这个公钥对应的私钥,就能在兼容握手中自己生成 CertificateVerify。

这份对象不是新的 X.509 证书,更不是下级 CA。RFC 9345 刻意只保留握手需要的语义:有效期终点、用于 CertificateVerify 的算法、公钥,以及终端证书私钥对这些字段的签名。签名还包含完整证书字节和客户端或服务端专用的上下文,因此同一份凭据不能在两个认证角色之间随意调换。

边缘得到的权力很实在。它能在有效期内代表证书持有者向兼容对端证明自己掌握一把获准的短期私钥。但它不能修改证书里的域名,不能向 CA 续期,不能用短期私钥签出下一份委托凭据,也不能让没有声明支持的客户端接受它。把这种权限写成“证书已交给 CDN”,会同时夸大边缘的制度权力并掩盖证书持有者仍保留的签发责任。

许可从长期证书开始

一张普通终端证书不能自动签出可接受的委托凭据。证书必须带有非关键的 DelegationUsage 扩展,并允许 digitalSignature。验证方缺少任何一项都必须拒绝。这个显式开关非常重要:临时接触普通证书私钥,或者从旧协议实现里得到一个签名 oracle,不应被暗中升级为生成任意 TLS 委托权限的能力。

服务端认证还有一道协商门。客户端先在 ClientHello 中发送编号 34 的 delegated_credential 扩展,并列出可以接受的委托 CertificateVerify 算法。服务端随后才可以把一份委托凭据放在终端证书的 CertificateEntry 中。客户端认证则反过来:服务端必须先在 CertificateRequest 中声明支持。未得到预先声明却擅自发送凭据,结果不是自动升级,而是握手失败。

收到对象后,客户端仍要按普通流程验证证书链和目标身份,然后检查当前时间、默认七天上限、不得超过证书到期日、两个算法字段、证书许可,以及终端证书私钥留下的签名。全部通过后,才用委托公钥验证这次握手的 CertificateVerify。

所以,线上看到的是四层事实:CA 接受了一张终端证书;该证书持有者批准了一份窄化对象;边缘在本次握手中证明掌握短期私钥;应用再决定这个已认证连接能做什么。上一层不能自动冒充下一层。

七天并不是撤回按钮

没有其他应用 profile 时,RFC 9345 要求委托凭据的剩余有效期默认不得超过七天,也不得越过长期证书的到期日。运营方可以选择更短。Cloudflare 的现行 Keyless 文档写明,其生成的委托凭据在关闭 Keyless 后会于 24 小时内失效。那是产品策略,不是 RFC 规定的统一寿命。

两种时间都不能写成“立即吊销”。RFC 9345 没有给单独一份委托凭据设计提前吊销服务。停止签发可以防止新对象出现,删除边缘配置可以阻止该节点继续使用,但已经复制出去的私钥不会被远程收回。正常终止依靠到期;吊销长期证书也会破坏委托的信任基础,却同时影响使用同一证书的其他连接。

时间本身还会故障。valid_time 以证书的 notBefore 为基准推导出到期点,验证方再用自己的时钟判断。边界附近的时钟偏差可能让服务端认为新凭据仍然有效,而部分客户端已经拒绝。轮换窗口必须包含时钟裕量、下一份凭据的提前部署和真实拒绝率,不能只看控制台上的日期。

会话恢复也不能绕开到期。若客户端恢复连接时缓存并重新验证证书链,就应把相关委托凭据一并缓存并重验。否则,凭据已经失效,旧的认证决定却可能通过恢复继续存在。

私钥怎样到达边缘

公开的委托对象本身不是主要风险;能生成 CertificateVerify 的短期私钥才是执行权。RFC 9677 在 CDN 互联里把两条路径说得很清楚。

第一条路径是下游 CDN 自己生成密钥对,只把公钥通过已认证的带外通道送给上游签发。私钥不离开下游,但公钥登记必须证明来自正确的节点或安全域。第二条路径是上游连同委托对象一起发送加密后的私钥。部署较集中,却产生了可保存的密文和一个负责解密的长期保护密钥。

RFC 9677 不建议通过元数据接口发送私钥。如果仍然这样做,私钥必须加密,保护强度也要足够;可是指定的信封并不对未来的解密密钥泄露提供前向保密。短期凭据过期后不能再建立新握手,不代表旧密文从归档中消失。

凭据粒度决定爆炸半径。一份凭据可以铺到许多边缘,轮换简单,却使任何一个副本泄露都牵连整组,握手记录也难以指出具体节点。每节点一份则便于归因和隔离,却把签名、配送、库存和到期故障成倍放大。合理边界不是图上画得最细的边界,而是系统在签名服务故障、部分节点离线和时钟异常时仍能可靠更新的最小边界。

兼容回退仍然握着长期路径

委托凭据只适用于 TLS/DTLS 1.3,并要求发起方明确声明。IANA 把编号 34 登记为推荐扩展,只证明语义稳定,不证明所有客户端或 CA 都已支持。

Cloudflare 当前文档一方面写明 Firefox 77 及以后版本支持,另一方面也明确说支持的客户端仍很少,能签发所需扩展的 CA 也只有少数。现实部署必然混合:支持的客户端走短期凭据;其他客户端仍需要普通证书私钥或远程签名。

回退路径不是背景噪声。远程签名增加每次握手的延迟和后端可用性依赖;把长期证书私钥复制到更多边缘,又重新扩大最初想缩小的风险;另发一张不带委托扩展的兼容证书,会增加续签与吊销库存。只统计“委托握手占比”而不看回退量和回源签名延迟,可能在新功能曲线上掩盖旧关键路径已经过载。

BoringSSL 的测试进一步证明算法边界不是一个字段:签署委托对象的算法,与短期公钥在 CertificateVerify 中使用的算法必须分别协商;TLS 1.2 必须拒绝;找不到合适委托凭据时可以选择普通证书。Mozilla NSS 的运行代码则在发送端选择委托私钥,在接收端选择委托公钥,并核对 CertificateVerify 算法。标准登记、配置存在和真实执行是三种不同证据。

一份可以复核的凭据账本

签发记录应保存长期证书指纹、序列号、名称、有效期、KeyUsage 与 DelegationUsage;委托对象的原始字节哈希、公钥哈希、认证角色、两个算法和推导出的到期点;以及谁批准、谁调用长期证书私钥完成签名。

保管记录应说明私钥由边缘生成还是接收而来,公钥登记或加密传送的通道,预定节点集合、实际部署确认和共享范围。握手记录应说明客户端是否声明支持、最终选择哪份凭据、证书和委托验证结果、CertificateVerify 是否成功、协议版本,以及是否回退到普通证书路径。

退役记录另成一组:停止后续签发的时间、各节点删除确认、最后理论有效时刻、是否吊销长期证书、会话恢复处理,以及到期后的负向握手测试。配置中看不见凭据,只能证明某个节点完成了一次本地修改;只有过期后拒绝和线上使用消失,才接近证明权限结束。

来源