1. 引言
本文基于 SignServer 社区版,面向验证 / PoC 场景,给出一套可复制的最小签名中心(CMS + TSA)实践;示例以可维护与可扩展为优先。文中涉及的 Keyfactor / EJBCA / SignServer 仅作开源实现示例,不构成任何背书。示例配置均为演示用途,生产上线需结合贵司的 mTLS/鉴权、密钥保护、审计留存、容量与高可用策略另行完善。
2. 架构与术语
-
SignServer:签名服务框架,内部以 Worker 为单位组织模块;
-
Worker:包括 Signer(如 CMSSigner、TimeStampSigner)与 Crypto Token(密钥与证书载体);
-
Crypto Token:
PKCS12(P12/JKS); -
Admin Web/CLI/REST:管理界面、命令行与 HTTP 接口。
3. 环境与前置条件
主机与系统
-
Ubuntu 20.04 Server(离线安装),4G+ RAM / 30G+ 磁盘(按并发放大);
-
容器运行时:Docker;docker‑compose 。
你已准备完毕,无需额外安装步骤。
证书与信任
- 管理端客户端证书 (由 EJBCA 的 ManagementCA 或等价 CA 签发),已导入浏览器。
持久化与权限(必读)
-
SignServer 容器对持久化目录以 UID=10001, GID=10001 写入;
-
必须将挂载到容器的目录设置为
10001:10001,否则读写失败。
3.1 目录与权限(复制即用)
# 项目目录(存放 compose.yml)
sudo mkdir -p /opt/signserver-compose/
# 持久化与证书目录(将被挂载进容器)
sudo mkdir -p /opt/signserver-data/ /opt/signserver-secrets/
# 关键:目录所有权设为 10001:10001(必须)
sudo chown -R 10001:10001 /opt/signserver-data/ /opt/signserver-secrets/
# 自检(应看到所有者/组均为 10001 10001)
ls -ld /opt/signserver-data/ /opt/signserver-secrets/
3.2 从 EJBCA 获取 ManagementCA.crt(PEM → CRT)
-
管理员浏览器打开:
https://<EJBCA主机或IP>/ejbca/adminweb/ca/cafunctions.xhtml例如:https://192.168.13.115/ejbca/adminweb/ca/cafunctions.xhtml -
在 CA Functions 页面下载 CA certificate (PEM/Base64),保存为
ManagementCA.pem。 -
转为
.crt(保持 PEM 编码),并放入挂载目录 /opt/signserver-secrets/:
# 假设浏览器下载到 ~/Downloads/ManagementCA.pem
sudo openssl x509 -in ~/Downloads/ManagementCA.pem -outform PEM \
-out /opt/signserver-secrets/ManagementCA.crt
# 设置所有者(与目录一致)
sudo chown 10001:10001 /opt/signserver-secrets/ManagementCA.crt
说明:
.crt为期望文件名/扩展名;内容保持 PEM(Base64)即可满足挂载使用。
3.3 (可选)为 Docker Daemon 配置 systemd 代理
适用场景:环境需通过 HTTP(S) 代理访问外网镜像仓库或网络资源时使用。请确保此操作符合贵司合规要求;示例中的 IP/端口与 NO_PROXY 请按你的实际网络替换。
创建代理配置
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf
在文件中添加以下内容(按需替换代理地址与 NO_PROXY):
[Service]
Environment="HTTP_PROXY=http://192.168.xx.xxx:7890"
Environment="HTTPS_PROXY=http://192.168.xx.xxx:7890"
Environment="NO_PROXY=127.0.0.1,localhost,192.168.13.116"
3.4 重新加载 systemd 并重启 Docker
执行以下命令让配置生效:
sudo systemctl daemon-reload
sudo systemctl restart docker
然后检查 Docker 是否正常运行:
sudo systemctl status docker --no-pager -l
如果 Active: active (running),说明 Docker 已成功启动。
3.5 验证代理是否生效
执行以下命令检查代理是否生效:
docker info | grep -i proxy
如果输出:
HTTP Proxy: http://192.168.xxx.xxx:7890
HTTPS Proxy: http://192.168.xxx.xxx:7890
说明 Docker Daemon 代理已生效!
4. 部署与初始化
4.1 用 vim 创建 compose(含 mTLS 管理)
# 打开文件(不存在则新建)
sudo vim /opt/signserver-compose/compose.yml
在 vim 中按 i 进入插入模式,粘贴以下内容;粘贴完按 Esc,输入 :wq 保存退出:
services:
signserver:
image: keyfactor/signserver-ce:latest
container_name: signserver
hostname: sign.example.local
environment:
- TLS_SETUP_ENABLED=true
- DATABASE_JDBC_URL=jdbc:h2:/mnt/persistent/signserverdb;DB_CLOSE_DELAY=-1
- DATABASE_USER=signserver
- DATABASE_PASSWORD=signserver
ports:
- "80:8080"
- "443:8443" # 建议仅启用 TLS 端口(PoC 亦同)
volumes:
- /opt/signserver-data:/mnt/persistent
- /opt/signserver-secrets/ManagementCA.crt:/mnt/external/secrets/tls/cas/ManagementCA.crt:ro
必须已完成:
/opt/signserver-data/、/opt/signserver-secrets/目录及其中的ManagementCA.crt文件,所有者均为 10001:10001(见第 3 章)。
4.2 启动与验证
cd /opt/signserver-compose/
docker compose up -d
# 查看容器
docker ps -a | grep signserver
# 快速检查日志(无输出则未发现 ERROR)
docker logs -f signserver | grep ERROR || echo "No ERROR found"
访问验证
- 管理界面(需导入管理员 P12):
https://<主机IP或域名>/signserver
成功标志
-
容器日志无
ERROR -
欢迎页可打开
5. 参考截图
5.1 SignServer 管理界面欢迎页
-
打开:
https://<主机IP或域名>/signserver -
需导入管理员 crt;欢迎页可正常显示。
5.2 点击 EJBCA AdminWeb 并下载 CA 证书(PEM/Base64)
-
打开:
https://<EJBCA主机或IP>/ejbca/adminweb -
顶部导航点击 CA Functions → 选择 CA certificate (PEM/Base64) → 下载。
图 2
6. 时间戳远程签名部署(Crypto Token + TimeStampSigner)
目标:基于 PKCS#12(P12) 证书私钥创建 Crypto Token,并绑定到 TimeStampSigner,完成 RFC‑3161 时间戳服务上线。
6.1 前置条件 & 约定(Docker Compose 映射版)
-
目录映射约定:
docker-compose.yml中将宿主机目录映射为容器内持久化目录:services: signserver: # 你的服务名可能不同 volumes: - /opt/signserver-data:/mnt/persistent:rw -
P12 放置位置(宿主机):请将时间戳证书
*.p12放到宿主机路径:/opt/signserver-data/,例如:-
宿主机:
/opt/signserver-data/Test_Timestamp_EE.p12 -
容器内(SignServer 看到的路径):
/mnt/persistent/Test_Timestamp_EE.p12
-
-
路径使用规范:后续在 SignServer 的
KEYSTOREPATH一律使用 容器内路径(/mnt/persistent/...)。 -
密码:已知该 P12 的访问密码。
-
证书来源建议(可选):建议搭配 Keyfactor EJBCA 证书服务器签发 TSA 证书(含 EKU
timeStamping),也可以使用任意受信 CA 颁发的现成 P12,流程保持一致。 -
快速自检(可复制执行):
# 1) 确保宿主机目录存在并放入 P12 sudo cp /path/to/Test_Timestamp_EE.p12 /opt/signserver-data/ # 2) 验证容器内可见(将 <svc> 替换为 compose 服务名signserver) cd /opt/signserver-compose docker compose exec <svc> ls -l /mnt/persistent | grep Test_Timestamp_EE.p12 -
示例参数沿用:
-
Crypto Token 名称:
CryptoTimestampG2 -
TimeStampSigner 名称:
TimeStampSignerG2 -
证书主题示例:
CN=Test Timestamp EE,O=Test,C=CN -
PSS 签名算法:
SHA256withRSAandMGF1
-
6.2 用 OpenSSL 确认 DEFAULTKEY(P12 私钥别名 alias)
DEFAULTKEY 必须填写 P12 中私钥条目的 friendlyName(别名),不要想当然使用证书的 CN。
命令:
# 会提示输入 P12 密码;不加 -nokeys 才能看到“Shrouded Keybag”
cd /opt/signserver-data/
openssl pkcs12 -in ./Test_Timestamp_EE.p12 -info
在输出中找到:
-
Shrouded Keybag段落下的:friendlyName: <这里就是 DEFAULTKEY>← 以此为准
-
(通常)与下面叶子证书的
Certificate bag→friendlyName:一致
例:若看到
friendlyName: Test Timestamp EE,则 DEFAULTKEY=Test Timestamp EE(大小写/空格都要完全一致)。
可选快速筛选:
openssl pkcs12 -in ./Test_Timestamp_EE.p12 -info \
| sed -n '/Shrouded Keybag/,/Certificate bag/p' | grep -m1 'friendlyName:'
6.3 新建 Crypto Token(KeystoreCryptoToken / P12)
图示:
操作路径:Workers → Add… → From TEMPLATE → keystore-crypto.properties(不是 From Properties),粘贴以下模板(把尖括号占位改成你自己的):
# === Crypto token for Test TSA (P12) ===
WORKERGENID42.TYPE=CRYPTO_WORKER
WORKERGENID42.IMPLEMENTATION_CLASS=org.signserver.server.signers.CryptoWorker
WORKERGENID42.CRYPTOTOKEN_IMPLEMENTATION_CLASS=org.signserver.server.cryptotokens.KeystoreCryptoToken
# 供其他工作者引用的名字(自定义,避免与现有重复)
WORKERGENID42.NAME=CryptoTimestampG2
# 使用 P12 文件
WORKERGENID42.KEYSTORETYPE=PKCS12
# 注意:这里必须写 **容器内路径**(compose 映射 /opt/signserver-data -> /mnt/persistent)
WORKERGENID42.KEYSTOREPATH=/mnt/persistent/Test_Timestamp_EE.p12
# 设置后可“自动激活”;若不想明文保存,可留空,改用手动 Activate
#建议:留空并手动 ACTIVATE,或使用机密管理注入(示例:/mnt/external/secrets/...)。请勿将任何密钥材料、P12 密码提交到公共仓库或截图中。
WORKERGENID42.KEYSTOREPASSWORD=<你的P12密码>
# 关键:填“私钥 Keybag 的 friendlyName”(区分大小写与空格)
WORKERGENID42.DEFAULTKEY=Test Timestamp EE
# 启用
WORKERGENID42.DISABLED=FALSE
激活与自检
-
选中新建的 CryptoTimestampG2 → 点击 ACTIVATE(若写了
KEYSTOREPASSWORD会自动激活)。 -
点击 TEST KEY…,应成功读取到
DEFAULTKEY对应密钥。
常见报错:
No such alias:
DEFAULTKEY与 P12 中的别名不完全一致(注意空格/大小写)。Token not active:未激活或密码错误。
6.4 新建 TimeStampSigner 并绑定到 Crypto Token
操作路径:Workers → Add… → From TEMPLATE → timestamp.properties(不是 From Properties),粘贴以下模板(把尖括号占位改成你自己的):
# === New TimeStampSigner (G2) ===
WORKERGENID66.TYPE=PROCESSABLE
WORKERGENID66.IMPLEMENTATION_CLASS=org.signserver.module.tsa.TimeStampSigner
WORKERGENID66.NAME=TimeStampSignerG2
# 认证
#⚠️ 仅限实验环境
WORKERGENID66.AUTHTYPE=NOAUTH
# 绑定新的 P12 加密令牌
WORKERGENID66.CRYPTOTOKEN=CryptoTimestampG2
# alias/friendlyName(已用 openssl 确认)
WORKERGENID66.DEFAULTKEY=Test Timestamp EE
# 策略(与你当前 worker 保持一致,可按需调整)
WORKERGENID66.DEFAULTTSAPOLICYOID=1.2.3.4.1
WORKERGENID66.TSAPOLICYIDS=1.2.3.4.5.6,1.2.3.4.5.7
#(仅 PoC;生产建议按需设置 DEFAULTTSAPOLICYOID/TSAPOLICYIDS)
WORKERGENID66.ACCEPTANYPOLICY=true
# 哈希/算法
WORKERGENID66.ESSCERTIDALGORITHM=SHA256
WORKERGENID66.TSA_ALLOWED_HASHES=SHA1,SHA256,SHA384,SHA512
# 使用 RSASSA-PSS
WORKERGENID66.SIGNATUREALGORITHM=SHA256withRSAandMGF1
# TSA GeneralName(建议与证书主题一致)
WORKERGENID66.TSA=CN=Test Timestamp EE,O=Test,C=CN
# 其余与现有保持一致
WORKERGENID66.MAXSERIALNUMBERLENGTH=16
WORKERGENID66.INCLUDESIGNINGTIMEATTRIBUTE=false
WORKERGENID66.INCLUDESTATUSSTRING=false
WORKERGENID66.DISABLEKEYUSAGECOUNTER=true
WORKERGENID66.VERIFY_TOKEN_SIGNATURE=true
WORKERGENID66.DISABLED=FALSE
自检
- 选中 TimeStampSignerG2 → TEST KEY… 应成功。
6.4.1 成功界面(示例)
当 CryptoTimestampG2 与 TimeStampSignerG2 都显示
ACTIVE,且 TEST KEY… 通过,即表示配置完成。
6.5 客户端请求示例(RFC‑3161)
建议用 workerName,避免 ID 改动带来影响。
# 准备个示例数据(你也可以换成自己的文件)
echo -n 'hello-tsa' > payload.bin
# 生成 TSQ(DER 格式)
openssl ts -query -data payload.bin -sha256 -cert -out sig.tsq
# 已有 sig.tsq(由 cms 签名值或原文生成的时间戳请求)
curl -k -H "Content-Type: application/timestamp-query" \
--data-binary "@sig.tsq" \
"https://<host>/signserver/process?workerName=TimeStampSignerG2" \
-o sig.tsr
查看/验证 TSR:
# 人类可读
openssl ts -reply -in sig.tsr -text
6.6 常见问题排查清单
-
别名不匹配:
DEFAULTKEY与 P12 私钥别名不同(检查空格、大小写、全角/半角)。 -
未激活:忘记 ACTIVATE 或
KEYSTOREPASSWORD填错。 -
链不完整:P12 导出时未携带中间证书,重新导出时加
-certfile chain.pem。 -
路径问题:
KEYSTOREPATH是 SignServer 进程内部可见 的路径(容器内路径)。 -
算法不一致:证书/密钥要求的算法与
SIGNATUREALGORITHM不匹配(如 PSS vs PKCS#1 v1.5)。 -
策略/哈希限制:请求的 Policy OID 或哈希算法不在允许列表内(检查
ACCEPTANYPOLICY/TSAPOLICYIDS/TSA_ALLOWED_HASHES)。
6.7 运行与维护建议
-
优先使用
workerName调用:/process?workerName=TimeStampSignerG2。 -
分环境/多算法:需要多套证书/策略时,可复制多个 TimeStampSigner(每个绑定不同 Crypto Token)。
-
密钥与配置备份:安全保存 P12、密码与导出的 Properties;生产上建议 HSM/P11。
-
前置负载/容灾:多节点部署 + 共享数据库,前面挂反向代理做健康检查与负载均衡。
6.8 一页式检查表
-
openssl pkcs12 -info确认 Shrouded Keybag → friendlyName -
新建 CryptoTimestampG2(P12 路径/密码/DEFAULTKEY)并 Activate
-
TEST KEY… 通过
-
新建 TimeStampSignerG2 并绑定
CryptoTimestampG2 -
TEST KEY… 通过
-
curl请求得到sig.tsr并openssl ts -reply -text检视
7. CMS 远程签名
目标:配置 CMSSigner 实现远程 CMS/PKCS#7 签名(支持 Detached 与 Attached),并给出可直接复制的
curl自测与openssl验证步骤。默认基于 P12 软证书,也可后续迁移 HSM/PKCS#11。
7.1 前置条件与目录映射
-
Compose 映射:
/opt/signserver-data:/mnt/persistent(容器内路径以/mnt/persistent为准)。 -
将 CMS 签名用 P12 放到宿主机:
/opt/signserver-data/Test_CMS_EE.p12(容器内即/mnt/persistent/Test_CMS_EE.p12)。 -
已知 P12 密码;已通过 6.2 的方法确认 friendlyName(
DEFAULTKEY)。 -
证书来源建议:推荐使用 Keyfactor EJBCA 为 CMS 用途签发(EKU:
codeSigning或按业务需求);当然也可直接使用任何受信 CA 的现成 P12。
可复用 6 章的 Crypto Token 吗?
安全与审计上更推荐独立:为 TSA 与 CMS 分配不同证书/令牌(如
CryptoTimestampG2与CryptoCMSG2)。若仅演示,可临时复用同一 P12,但生产不建议。
7.2 新建 Crypto Token(KeystoreCryptoToken / P12)
操作路径:Workers → Add… → From TEMPLATE → keystore-crypto.properties(KeystoreCryptoToken 模板)。
图示:
导入模板后,检查/覆盖以下关键项(保持容器路径规范):
# === Crypto token for Test CMS (P12) ===
WORKERGENID52.TYPE=CRYPTO_WORKER
WORKERGENID52.IMPLEMENTATION_CLASS=org.signserver.server.signers.CryptoWorker
WORKERGENID52.CRYPTOTOKEN_IMPLEMENTATION_CLASS=org.signserver.server.cryptotokens.KeystoreCryptoToken
WORKERGENID52.NAME=CryptoCMSG2
WORKERGENID52.KEYSTORETYPE=PKCS12
# 注意:容器内路径
WORKERGENID52.KEYSTOREPATH=/mnt/persistent/Test_CMS_EE.p12
# 不想明文保存可留空,改用手动 Activate
#建议:留空并手动 ACTIVATE,或使用机密管理注入(示例:/mnt/external/secrets/...)。请勿将任何密钥材料、P12 密码提交到公共仓库或截图中。
WORKERGENID52.KEYSTOREPASSWORD=<你的P12密码>
# P12 私钥 Keybag 的 friendlyName(区分大小写与空格)
WORKERGENID52.DEFAULTKEY=<你的DEFAULTKEY>
WORKERGENID52.DISABLED=FALSE
激活与自检:选中 CryptoCMSG2 → ACTIVATE → TEST KEY… 应成功。
7.3 新建 CMSSigner 并绑定 Crypto Token(定长配置)
操作路径:Workers → Add… → From TEMPLATE → cmssigner.properties(CMSSigner 模板)。
图示:
按“定长”要求的属性集(与示例界面一致,可直接复制):
# === Test_CMSSigner (Fixed profile) ===
WORKERGENID77.TYPE=PROCESSABLE
WORKERGENID77.IMPLEMENTATION_CLASS=org.signserver.module.cmssigner.CMSSigner
WORKERGENID77.NAME=Test_CMSSigner
# 鉴权策略(如在内网/前置网关受控场景):
#⚠️ 仅限实验环境
WORKERGENID77.AUTHTYPE=NOAUTH
# 绑定 Crypto Token(若你的 7.2 名称不同,请相应替换)
WORKERGENID77.CRYPTOTOKEN=CryptoCMSG2
WORKERGENID77.DEFAULTKEY=Test Code Signing EE
# 算法(示例为 RSA-PSS):
WORKERGENID77.SIGNATUREALGORITHM=SHA256withRSAandMGF1
# 允许的摘要算法集合(固定三种):
WORKERGENID77.ACCEPTED_HASH_DIGEST_ALGORITHMS=SHA-256,SHA-384,SHA-512
# 允许客户端指定摘要/是否分离签名(客户端可覆盖):
WORKERGENID77.ALLOW_CLIENTSIDEHASHING_OVERRIDE=TRUE
WORKERGENID77.ALLOW_DETACHEDSIGNATURE_OVERRIDE=TRUE
# 输出为分离签名(.p7s);如需附带内容请改为 FALSE:
WORKERGENID77.DETACHEDSIGNATURE=TRUE
# 其他与示例界面一致:
#默认携带证书链(可选)
#WORKERGENID77.INCLUDECERTIFICATELEVEL=Chain
WORKERGENID77.DER_RE_ENCODE=TRUE
WORKERGENID77.DISABLEKEYUSAGECOUNTER=TRUE
WORKERGENID77.DISABLED=FALSE
界面参考(定长属性示例):
自检:选中 Test_CMSSigner → TEST KEY… 应成功(若失败,多半是 CRYPTOTOKEN/DEFAULTKEY 或证书算法不匹配)。
7.4 成功界面(示例)
成功界面(示例)
CryptoCMSG2 与 Test_CMSSigner 均为
ACTIVE,且 TEST KEY… 通过。
7.5 客户端请求示例(curl:两种方式,写死示例)
小/中等文件用“非预哈希”(原文直传);大文件务必用“预哈希”。输出统一为 data.bin.cms。
7.5.1 非预哈希(原文直传)
# 原文:data.bin
# 输出:data.bin.cms
#⚠️ 仅限实验环境
curl -k \
-F workerName=Test_CMSSigner \
-F file=@data.bin \
--output data.bin.cms \
"https://<host-or-ip>/signserver/process"
7.5.2 预哈希(大文件推荐)
# 第一步:生成“二进制”摘要(不是十六进制字符串)
openssl dgst -sha256 -binary data.bin > data.bin.sha256
# 第二步:以 multipart/form-data 方式提交:
# - file 上传的是上一步得到的 data.bin.sha256
# - 通过 REQUEST_METADATA.* 传入客户端预哈希的元数据
#⚠️ 仅限实验环境
curl -k \
-F workerName=Test_CMSSigner \
-F REQUEST_METADATA.USING_CLIENTSUPPLIED_HASH=true \
-F REQUEST_METADATA.CLIENTSIDE_HASHDIGESTALGORITHM=SHA-256 \
-F file=@data.bin.sha256 \
--output data.bin.cms \
"https://<host-or-ip>/signserver/process"
大文件必须用预哈希,否则可能因上传超时/内存占用导致失败或非常慢。
7.6 使用 OpenSSL 本地验证(仅验证签名正确性)
只检查“签名 = 原文 + 私钥”是否匹配,不校验证书链/EKU/有效期。适用于快速自检或签名链尚未就绪的场景。
7.6.1 分离签名(Detached)
# 原文:data.bin
# 签名:data.bin.cms(DER)
#⚠️ 仅限实验环境
openssl cms -verify \
-binary -inform DER \
-in data.bin.cms \
-content data.bin \
-noverify \
-out /dev/null && echo "OK"
#⚠️ 仅自检:以上命令只验证签名完整性
7.7 常见问题排查
-
No such alias / bad alias:
DEFAULTKEY与 P12 中 friendlyName 不一致(参考 6.2)。 -
Token not active:未激活、密码错误或 P12 路径未按容器内路径填写。
-
Algorithm mismatch:证书/策略不允许所选算法(PSS vs PKCS#1 v1.5)。
-
Detached/Attached 不符:确认
DETACHEDSIGNATURE设置;不同版本模板的覆盖策略可能不同。 -
链不完整:签名可成功但验证失败;将
-CAfile指向包含中间证书的 bundle 文件,或修正服务端证书链配置。
7.8 迁移到 HSM/PKCS#11(提要)
-
将 7.2 中的
KEYSTORETYPE=PKCS12改为PKCS11,并按厂商文档配置:-
P11LIBRARY=/usr/local/lib/your_hsm_pkcs11.so -
P11SLOTLABEL/P11SLOT/P11TOKENLABEL -
DEFAULTKEY=<HSM 内的 key label>
-
8. openUBMC × Keyfactor/EJBCA & SignServer:应用场景与验证
目的:给出 openUBMC 在两个开源平台组合下的落地方式与验证路径,不涉及实现细节。
hpm_signer:需要结合项目做适配后再用于远程 CMS 签名。当前hpm_signer基于 SignServer 的适配已完成,PR 已提交至社区bingo仓库,如有需要可自行提前获取代码进行验证。
hpm_verify:可直接用于校验签名结果,现阶段用于联调。
8.1 两种场景
场景 A:企业 CA = Keyfactor EJBCA,签名中心 = SignServer
openUBMC → (适配后)hpm_signer → SignServer·CMSSigner(可选 TSA)
↓
*.cms(+ *.tsr) → 分发/入库
场景 B:仅使用 SignServer(证书来自预置 P12 或 HSM)
openUBMC → (适配后)hpm_signer → SignServer·CMSSigner(可选 TSA)
↓
*.cms(+ *.tsr) → 分发/入库
说明: 两种场景在 openUBMC 侧一致;差别仅在证书来源与签发流程。联调阶段建议先完成服务端(第 6–7 章)并用
hpm_verify验证链路。
当前hpm_signer基于 SignServer 的适配已完成,PR 已提交至社区仓库,如有需要可自行提前获取代码进行验证。
8.2 现阶段验证(先用 hpm_verify)
直接用
hpm_verify对第 7.5 生成的*.cms做校验,确认链路正确。
验证命令
# 分离签名:原文 + CMS(DER)
./hpm_verify -r rootca.pem -c uboot.bin -s uboot.bin.cms && echo "OK"
仅做完整性快速自检也可参考第 7.6 的
openssl cms -verify -noverify单条命令。
8.3 常见问题(概述)
-
返回 HTML/XML:多为预哈希表单字段错误;按 7.5.2 的
REQUEST_METADATA方式处理。 -
链不完整:请在服务端开启
INCLUDECERTIFICATELEVEL=Chain后重新签名。 -
用途报错:若使用 OpenSSL 的全量验证,可能遇到
unsuitable certificate purpose;联调阶段建议仅做完整性检查(见 7.6),或在验证端放宽用途。















