2. 证书链与身份验证:设备认证证书(DAC)结构、产品认证证书(PAI)与根证书、证书验证流程与常见失败原因

证书链验证,说白了就是Matter设备入网的「身份证核验」。你想想看,一个灯泡、一个插座,凭什么能加入你的智能家居网络?就凭它手里那套证书。我做了这么多年嵌入式安全,见过太多设备因为证书问题被拒之门外。今天咱们就把这套机制彻底讲透。

2.1 三张证书,各司其职

Matter的证书链分三层,从上到下依次是:根证书、产品认证证书(PAI)、设备认证证书(DAC)。每一层都有明确的职责边界。

核心原则:根证书是信任锚点,PAI是产品线身份,DAC是设备个体身份。验证时从DAC往上追溯,直到信任的根证书。

2.1.1 设备认证证书 (DAC)

DAC是每台设备出厂时烧录的唯一身份证。它绑定了设备的公钥和产品信息。我在项目中遇到过一批设备,DAC里的vid:pid写错了,结果整个批次都无法入网——嗯,这种低级错误其实挺常见的。

DAC的核心字段:

  • Subject (主体):包含设备的VID(厂商ID)和PID(产品ID),格式为 vid:pid
  • Subject Public Key Info:设备的公钥,用于后续的密钥协商
  • Issuer (签发者):指向签发它的PAI证书
  • Serial Number:设备序列号,唯一标识

2.1.2 产品认证证书 (PAI)

PAI代表一个产品系列。同一型号的灯泡,共享同一个PAI。它由CSA(连接标准联盟)或厂商自签的根证书签发。

PAI的关键作用:

  • 验证DAC是否来自合法的产品线
  • 携带产品级别的VID/PID信息
  • 作为DAC和根证书之间的桥梁

2.1.3 根证书 (Root Certificate)

根证书是整个信任链的起点。它通常是CSA颁发的,或者由厂商自己的根CA签发(用于测试环境)。根证书是自签名的,意味着它自己证明自己。

注意:根证书必须预先安装在Matter控制器(如手机、智能音箱)的信任存储中。如果根证书缺失或过期,整个证书链验证都会失败。我曾经排查过一个案例,用户升级了手机系统,结果根证书被清除了——设备死活配不上对。

2.2 证书链验证流程

验证过程其实不复杂,但每一步都可能出问题。我习惯把它拆成四个步骤:

  1. 格式检查:解析DAC,检查字段完整性、有效期、签名算法
  2. 签名验证:用PAI的公钥验证DAC的签名
  3. 向上追溯:用根证书的公钥验证PAI的签名
  4. 信任锚检查:确认根证书在控制器的信任列表中

下面这张图把流程画清楚了:

Matter证书链验证流程 Matter 证书链验证流程 设备认证证书 (DAC) ① 格式检查:字段、有效期、算法 产品认证证书 (PAI) ② 用PAI公钥验证DAC签名 根证书 (Root CA) 验证方向 从DAC向上追溯 直到信任的根证书 常见失败点 签名不匹配 证书过期 / 根缺失

2.3 常见失败原因与排查方法

证书验证失败,是Matter设备入网失败的头号原因。我整理了一份清单,按出现频率排序:

失败原因 典型表现 排查方向
DAC签名无效 验证时抛出 kCertChainFails 错误 检查DAC是否被篡改,PAI公钥是否正确
证书过期 时间戳校验失败 检查设备系统时间,证书有效期
根证书缺失 控制器找不到匹配的根证书 确认根证书已正确安装到信任存储
VID/PID不匹配 DAC中的VID/PID与PAI不一致 核对产品注册信息,重新签发证书
证书格式错误 解析时崩溃或返回空指针 用 openssl x509 -text 检查DER编码

2.3.1 签名验证失败

这是最常见的问题。DAC的签名是用PAI的私钥生成的,验证时用PAI的公钥。如果公钥和私钥不匹配,或者DAC内容被修改过,签名就会失效。

我建议你在固件里加一个自检函数,设备启动时先验证自己的DAC签名。这样能提前发现问题,而不是等到入网时被拒绝。

// 伪代码:设备自检DAC签名
bool verifyDacSignature(const uint8_t* dac, size_t dacLen, const uint8_t* paiPubKey) {
    // 1. 解析DAC,提取签名值
    // 2. 用PAI公钥验证签名
    // 3. 返回验证结果
    return Crypto::ECDSA_verify(dac, dacLen, paiPubKey);
}

2.3.2 证书过期

证书都有有效期。DAC和PAI通常有5-10年有效期,根证书更长。但设备如果长时间未联网,系统时间可能不准。我记得有个客户反馈设备无法入网,查了半天发现是设备时间停留在1970年——证书还没生效呢。

小技巧:在设备出厂测试时,强制设置一个未来的时间点,验证证书是否会在「未来」过期。这样可以提前发现证书有效期设置过短的问题。

2.3.3 根证书信任问题

控制器的信任存储里必须有根证书。如果根证书被删除、损坏或未安装,验证就会失败。Matter规范要求控制器至少预装CSA的根证书,但有些厂商会添加自己的根证书。

我曾经排查过一个案例:用户用手机A配网成功,用手机B却失败。原因是手机B的信任存储里缺少厂商的根证书。解决方案是让设备在配网时主动发送完整的证书链(DAC + PAI + 根证书),而不是只发DAC。

2.4 实战:用OpenSSL检查证书链

在开发阶段,我习惯用OpenSSL手动验证证书链。下面是一个完整的命令序列:

# 1. 查看DAC内容
openssl x509 -in dac.der -inform DER -text -noout

# 2. 验证DAC的签名(用PAI公钥)
openssl verify -CAfile pai.pem -untrusted dac.pem dac.pem

# 3. 验证完整证书链
openssl verify -CAfile root.pem -untrusted pai.pem dac.pem

# 4. 检查证书有效期
openssl x509 -in dac.der -inform DER -noout -dates

如果验证失败,OpenSSL会给出具体的错误信息。比如:

  • certificate has expired —— 证书过期
  • unable to get local issuer certificate —— 找不到签发者证书
  • signature verification failed —— 签名不匹配

2.5 避坑指南

最后,分享几个我踩过的坑:

  • 证书编码搞混:DAC通常是DER格式,但有些工具默认输出PEM。两者不兼容,解析时会报错。用 openssl x509 -inform DER -in dac.der 确认格式。
  • 私钥泄露:PAI的私钥如果泄露,攻击者可以伪造DAC。建议把私钥存储在HSM(硬件安全模块)中,不要明文放在固件里。
  • 证书链不完整:设备在配网时只发送DAC,不发送PAI和根证书。控制器如果本地没有PAI,就无法验证。解决方案是让设备发送完整的证书链。
  • 测试证书和正式证书混用:开发阶段用自签根证书,生产阶段用CSA根证书。两者不能互换。我见过有人把测试证书烧录到量产设备里,结果全部无法入网。

重要提醒:证书链验证是Matter安全的第一道防线。不要为了省事跳过任何一步。我曾经接手过一个项目,工程师为了调试方便,把证书验证写成了「总是返回成功」——结果产品上市后被人轻松破解。嗯,这个教训挺深刻的。