bingo 本地sign server云签名curl验证

背景:

openubmc使用的是 华为 openUBMC 工程自带的 hpm_signer 工具,用于对固件镜像(如 uboot.bin)进行签名,并通过本地 tsa.cnf 配置添加 RFC 3161 时间戳,形成一个完整的 CMS Detached 签名 + 时间戳结构(即 CAdES-T)。目前这套流程效果如下:


:puzzle_piece: hpm_signer 实际做了哪些操作?

我们直接拿cms文件用openssl查看结构后确认,它完成了如下完整签名流程:

步骤 说明
① 读取cms文件,如 uboot.bin.cms
② 计算 SHA-256 摘要
③ 构造 CMS SignedData 结构,签名算法为 sha256WithRSAEncryption,生成 Detached 签名(不嵌入原始内容)
④ 添加 SignedAttributes:包括 contentTypesigningTimemessageDigestid-smime-aa-signingCertificateV2
⑤ 使用 RSA 私钥签名 SignedAttributes
⑥ 将签名值进行 SHA-256 摘要
⑦ 根据 tsa.cnf 配置,通过本地 HTTP 或本地私钥生成 RFC 3161 TimeStampToken
⑧ 将时间戳(TimeStampToken)封装为 UnsignedAttributes,OID 为 1.2.840.113549.1.9.16.2.14(即 signatureTimeStampToken
⑨ 输出最终 CMS 签名文件:例如 uboot.bin.cms

签名结果结构见 openssl cms -inform DER -cmsout -print 可确认,确实嵌入了 RFC 3161 时间戳。


:light_bulb:问题:

我们希望将签名操作迁移至云签名架构,即使用 SignServer 作为 TSA 或 CMS 签名服务。

但发现如下问题:

  1. hpm_signer 当前必须依赖本地 tsa.cnf 文件;
  2. 而 SignServer 提供的是基于 HTTP 接口的 TSA,不会提供 .cnf 文件;
  3. 因此初步判断,要替换掉 hpm_signer,要么需要重写它,要么需要替代工具完成类似功能吗。

:red_question_mark:我想请教社区以下问题:

  1. 是否有大佬实现过类似迁移,把 hpm_signer 的 TSA 机制替换为 SignServer(例如通过 SignServer 的 Extended CMS Signer 或其他接口)?
  2. 是否有办法用 openssl cmsopenssl ts 等命令结合脚本完成同样流程(包括时间戳嵌入)?
  3. 如果要重写一个精简版的 hpm_signer,是否有示例代码?

我们目前的证书和签名服务器不是基于 OpenSSL 的,也没有 tsa.cnf 文件,因此现有的 hpm_signer 不太适配。
但应该是支持通过 OpenSSL 调用 URL 方式发起签名请求,在其他帖子上有验证。
能否提供 hpm_signer 内部对应的 OpenSSL 命令步骤,方便我们评估是否可通过修改命令适配现有流程?


:white_check_mark: 测试背景:

我用如下命令(OpenSSL 3.0.13,Ubuntu 24.04)重新生成了签名:

openssl cms -sign -binary  \
-signer signer.pem -inkey signer.pem -in uboot.bin -md sha256 -cades \
 -nosmimecap  -outform DER -out step.cms

然后用 hpm_verify 进行验证:

hpm_verify -r rootca.pem -C cms.crl.pem -c uboot.bin -s step.cms

结果:Verification successfully :white_check_mark:

但我注意到,这个 step.cms 文件:

  • 完全是 OpenSSL 生成的;
  • 没有添加时间戳(没有 unsignedAttrs,没有 OID 1.2.840.113549.1.9.16.2.14);
  • hpm_signer 最终生成的 .cms(含时间戳)在结构上有明显差异。

目前来看,OpenSSL 的本地时间戳签名流程(基于 tsa.cnf 配置)中,通常需要手动提取 CMS 中的签名值作为时间戳请求输入;签名完成后,还需通过工具将时间戳重嵌入 CMS。从现有实现看,hpm_signer 内部似乎是直接通过 OpenSSL 库将时间戳 token 写入 CMS 的。

但如果使用云端或第三方签名中心(非 OpenSSL TSA),则一般不依赖 tsa.cnf,签名值的提取步骤可能也不是必要的(这部分仍有待验证)。

不过仍有一个问题:在使用外部签名中心返回的时间戳 token(.tsr)时,是否仍需要依赖 OpenSSL 库将其注入原始 CMS 中?

需要进行二次嵌入,使用openssl库,因为24.04的openssl版本过于低。
目前使用openssl命令签名+生成时间戳token+openssl库的C代码实现签名+二次嵌入CMS验证目前应该是没问题。
后续需要将tsa.cnf文件删除,时间戳签名使用openssl+url配合云签名中心


通过重新学习 SignServer 的架构后了解到:在开源社区版中,虽然支持基础 CMS 签名和时间戳响应(TSR)的生成,但仍需基于签名值手动创建时间戳请求(TSQ)再获取 TSR,再手动将其嵌入至 CMS 签名中,即仍需二次处理签名结果。而在企业付费版中,提供了更高的集成度,可通过一条 curl 命令自动完成 TSQ 生成、TSR 请求及其注入 CMS 签名的全过程,显著简化操作流程。

参考 hpm_signer 的源码:
GitCode - 全球开发者的开源社区,开源代码托管平台

谢谢大佬,原来代码是开源的 :anxious_face_with_sweat: