CMS 多主签名者

HotPDF 可以创建一个 RFC 5652 SignedData 容器,其中最多包含 256 条彼此独立的主 SignerInfo 记录

构建请求

每个 THPDFCMSPrimarySignerRequest 自带证书与密钥材料、文档摘要、THPDFCMSSignOptions、可选的 THPDFSignatureProvider 以及 provider 密钥标识符

HPDFCMSBuildMultiSignedData 会先校验所有请求,再去调用任何本机密钥、外部 callback、时间戳 callback、PDF MAC callback 或 provider,避免后面的无效请求造成本可避免的部分远程签名开销

SetLength(Signers, 2);
Signers[0].KeyMaterial := FirstKey;
Signers[0].DocumentDigest := HPDFCMSDigestBytes(DocumentBytes, cmsdaSHA256);
Signers[0].Options := FirstOptions;

Signers[1].KeyMaterial := SecondKey;
Signers[1].DocumentDigest := HPDFCMSDigestBytes(DocumentBytes, cmsdaSHA384);
Signers[1].Options := SecondOptions;
Signers[1].Provider := RemoteProvider;
Signers[1].KeyIdentifier := 'approval-key';

CMS := HPDFCMSBuildMultiSignedData(Signers);

确定性合并

HPDFCMSMergeSignedData 可以合并已构建好的 CMS 容器,适配异步或分布式签名工作流,无需重复私钥运算

每个输入必须使用定长(definite-length)signedData 信封和集合,必须声明其主签名者用到的所有摘要算法,并且必须携带逐字节相同的 encapContentInfo;额外声明的摘要算法依然允许

合并后的容器会对摘要算法、证书和吊销值去重,按 DER 字节序对所有 SET OF 值排序,保留每一个主签名者,并把外层版本号提升到所有输入中的最高有效要求

编码之后请求顺序刻意不可观测,因为 signerInfos 是 DER SET OF;因此解析和验证结果按 DER 顺序而非请求顺序给出

单签名者构建与单容器合并会逐字节保留原有 CMS 内容

独立校验

HPDFParseCMSSignatures、HPDFVerifyCMSSignaturesEx 和 HPDFVerifyCMSSignerReport 会为每个主签名者返回独立结果,涵盖其属性、摘要与签名策略、匹配的证书、时间戳、会签(counter-signature)和失败状态

某个格式错误或密码学上无效的签名者不会抹掉有效兄弟结果;但只要有一个主签名者未通过,聚合布尔结果就是 false

占位符尺寸估算

HPDFCMSEstimateMultiSignerPlaceholder 在不实际签名的前提下推导每个签名长度,用合成签名值构建精确去重后的静态容器形状,累加动态 callback 预留,最后一次性应用配置好的全局安全余量、对齐、最小值和最大值

THPDFCMSPlaceholderEstimateInfo.SignatureBytes 报告所有主签名者的总和,cpesMixed 表示各签名者使用了不同的估算来源

PDF 工作流边界

多签名者 API 暴露的是通用 CMS 能力,面向那些消费 profile 允许单容器内多个主签名者的应用

许多 PDF 签名和 PAdES 工作流在每个签名字典中只建模一个主签名者,所以除非接收方 profile 明确接受多签名者 CMS,否则请使用独立的 PDF 签名字段

参见 CMS SubjectKeyIdentifier 签名者、CMS 摘要算法一致性和 CMS 占位符自动估算