DAT 证书

1. 概述

DAT 证书是用于控制 DAT 的签发权限,并管理令牌的签名及加密算法与密钥(Key)信息的规范。

每张证书都拥有唯一的 ID(CID),通过强制约束 DAT 的可签发期限以及所生成令牌的有效期(TTL),安全地管理令牌的生命周期。

在 DAT 中,密钥轮换不是可选项。 因为证书在规范层面就写死了可签发期限,一旦超出该期限,就无法再用该证书生成新的令牌。


2. 证书结构

证书传输格式
cid
uint64 (十六进制)
.
start
uint64 (十进制)
.
duration
uint64 (十进制)
.
ttl
uint64 (十进制)
.
sig-alg
String
.
crypto-alg
String
.
sig-key
Base64Url
.
crypto-key
Base64Url
将鼠标悬停在各字段上即可查看说明。
cid . start . duration . ttl . sig-alg . crypto-alg . sig-key . crypto-key
结构
示例refresh

2.1. 各字段详细规范

CID : Hex (uint64)

  • 用于标识证书的唯一证书 ID。它与 DAT 的 CID 字段映射,在验证时决定使用哪张证书。
  • CID 是不可变的标识符。 更换密钥时不复用同一个 CID,而是以新的 CID 签发证书。

DAT颁发开始时间 : uint64 (Unix Time)

  • 以秒(Seconds)为单位表示可以使用该证书签发 DAT 的开始时间

DAT颁发期限 : uint64 (Seconds)

  • 证书的签发有效期限。自 DAT颁发开始时间 起经过本期限(秒)之后,将无法再使用该证书签发新的 DAT。
  • 它是一段时长(duration),而不是绝对时刻。 结束时刻由 start + duration 计算得出。

DAT TTL (有效时间) : uint64 (Seconds)

  • 由该证书签发的 DAT 的有效期(Time To Live)。生成 DAT 时,expire 值会设置为签发时刻加上该值的结果。

签名算法 : String / Enum

  • 生成和验证 DAT 的 signature 字段时所使用的签名算法

加密算法 : String / Enum

  • 加密和解密 DAT 的 secure 字段时所使用的加密算法

签名密钥 : Base64Url (Binary)

  • 用于签名及验证的密钥数据。(根据算法不同,可以是非对称密钥的 Public/Private Key,也可以是对称密钥。)

加密密钥 : Base64Url (Binary)

  • 用于 secure 字段加解密的加密密钥数据。

2.2. 时间计算

end    = start + duration        签发结束时刻
expire = end + ttl               证书的最终过期时刻
  • 所有计算都在 uint64 上进行,只有溢出才会被判为错误并拒绝。
  • duration = 0ttl = 0 都是合法的值。它们可以表示签发窗口立刻关闭的证书,或者签发后立即失效的令牌所对应的证书。
  • 由于各字段都是无符号整数,从类型上就不存在负数。

2.3. 构造函数签名

所有语言的实现都使用以下参数顺序。

(cid, dat_issuance_start_seconds, dat_issuance_duration_seconds, dat_ttl_seconds,
 signature_key, crypto_key)

第三个参数是时长,而不是结束时刻

如果把绝对结束时刻(end)传给第三个参数,不会报错,却会生成有效窗口完全错乱的证书。因为该值会被原样代入 start + duration


3. 证书的生命周期

证书的四个区间
创建
开始签发
结束签发
最终过期
签发延迟 (delay)
可签发 (duration)
DAT TTL
让所有节点取走证书的时间
DAT 签发 + 验证均可
不可签发,只能验证
证书要在经过签发延迟 → 可签发 → DAT TTL 剩余区间之后,才会最终过期。
区间签发验证判定
签发延迟issuable() == false
可签发issuable() == true
DAT TTL 剩余签发窗口已关闭,但尚未过期
最终过期之后expired() == true
  • 是否可签发signable() && start <= now <= end 判定,且包含两端
  • 即使签发窗口关闭之后,证书仍会多存活 ttl 的时长。因为在窗口即将关闭之前签发的令牌,必须能够走完自己的寿命。
  • 签发延迟(delay) 区间是为了给集群中所有节点争取时间来取走新证书。详细内容请参阅 CMS 同步 文档。

4. 算法

4.1. 签名算法

用于防止 DAT 被伪造或篡改的签名算法列表。支持对称密钥与非对称密钥两种方式。

名称方式备注
ECDSA-P256非对称椭圆曲线数字签名(NIST secp256r1)
ECDSA-P384非对称椭圆曲线数字签名(NIST secp384r1)
ECDSA-P521非对称椭圆曲线数字签名(NIST secp521r1)
HMAC-SHA256-MFS对称基于 256-bit 固定长度密钥的 Keyed-Hashing
HMAC-SHA384-MFS对称基于 384-bit 固定长度密钥的 Keyed-Hashing
HMAC-SHA512-MFS对称基于 512-bit 固定长度密钥的 Keyed-Hashing

MFS(Maximum Fixed Secret): 使用与哈希算法输出(Output)位数相同的固定长度密钥的方式。

4.2. 加密算法

用于保护 DAT 内部机密数据(secure 字段)的已认证加密(Authenticated Encryption)算法列表。

名称密钥长度结构
IV-AES128-GCM128-bitIV(96bit) + 加密结果
IV-AES256-GCM256-bitIV(96bit) + 加密结果

IV(Initialization Vector)内置化: 每次加密时生成的唯一 96 位 NONCE(IV)以前缀(Prefix)形式拼接在加密结果之前。解密时先将前 96 位分离作为 IV,再执行解密。

4.3. 密钥长度校验

读取证书时,会确认所声明算法的位数与实际密钥长度是否一致

例如,声明为 IV-AES256-GCM 的证书中若含有 16 字节的密钥,则导入本身就会被拒绝。若没有这项检查,就会出现自以为在使用 AES-256、实际上却按 AES-128 运行的情况。


5. verify-only 导出

对于只执行验证的服务器,没有必要交给它签名用的私钥。为此,DAT 证书提供了 verify-only 导出

完整证书与 verify-only 证书的分发路径
DAT CMS
签发服务器
仅验证服务器
GET /v1/certs
完整证书(含签名私钥)
GET /v1/certs/verify-only
verify-only 证书
请求证书分发
签名算法support_verify_only()verify-only 导出结果
ECDSA 系列true签名密钥只输出公钥(Base64 由 130 字符变为 87 字符)
HMAC 系列false会产生显式错误

HMAC 是对称密钥,因此不存在“只能用于验证的密钥”这种东西。所以在尝试 verify-only 导出时,不会被悄悄跳过,而是立即以错误的形式告知。 一旦混入了 HMAC 证书,调用 verify-only 导出就会失败;因此如果要运行仅验证的节点,就必须使用 ECDSA 系列。

加密密钥在 verify-only 中同样会完整输出

用于 secure 字段的 AES 密钥是对称密钥,因此无论是否 verify-only,都始终完整导出。 因为解密需要与加密时相同的密钥。

也就是说,收到 verify-only 证书的服务器:

  • 无法伪造签名 —— 由于没有私钥,它无法生成新的 DAT。
  • 可以解密 secure 载荷 —— 对它们并不提供机密性。

verify-only 是划分签发权限的手段,而不是划分机密性的手段。如果某个值需要对验证节点保密,就不应该放进 secure