THotPDF.SignPDFWithPFX

THotPDF

 

上一页  方法  AddPubKeyRecipient

使用 PFX / PKCS#12 文件对现有 PDF 占位符执行签名,构建 CMS SignedData 容器并一次调用就将已签名 PDF 写出

 

Delphi 语法 (file overload):

class function SignPDFWithPFX(

  const InputPDFPath: string;

  const OutputPDFPath: string;

  const PFXFilePath: string;

  const Password: AnsiString): boolean; overload; static;

 

Delphi 语法 (stream overload):

class function SignPDFWithPFX(

  InputStream: TStream;

  OutputStream: TStream;

  const PFXFilePath: string;

  const Password: AnsiString): boolean; overload; static;

 

说明

SignPDFWithPFX 是 v2.119.27 加入的端到端 PFX 签名入口。输入 PDF 必须已包含由 THPDFPage.AddSignedSignatureField(或其 PAdES 包装)写出的签名占位符,subFilter 为 adbe.pkcs7.detached。该方法:   1. 加载输入 PDF,定位 /ByteRange + /Contents sentinel 占位符,并用实际字节偏移修补 /ByteRange 2. 加载 PFX 文件并用提供的密码解密。PBES2 接受 AES-128-CBC、AES-192-CBC 和 AES-256-CBC,PBKDF2 PRF 默认为 HMAC-SHA-1,也可显式指定 HMAC-SHA-256、HMAC-SHA-384 和 HMAC-SHA-512。可选的 PBKDF2 keyLength 必须与所选 AES 密码匹配;旧式 PBE-SHA1-3DES 文件仍受支持,用于较老的证书导出。其他加密配置会抛出带违规 OID 的诊断 3. 对 /ByteRange 覆盖的文档字节计算 SHA-256,并构建 CMS SignedData(RFC 5652)DER blob,其中包含 X.509 证书、签名属性(contentType + messageDigest + signingTime)以及针对 SET-tagged signed attributes 的 RSA + SHA-256 签名 4. 将 CMS DER 十六进制编码,确认其适合 AddSignedSignatureField 预留的 /Contents 空间(默认 8 KB 可覆盖 1024 / 2048-bit RSA),再注入占位符 5. 将修补后的字节写入输出路径或流

 

1. 经有界的 256 KB 缓冲复制输入,或复用同一可 seek 的可读写流;定位 /ByteRange + /Contents 占位符,并用实际字节偏移 seek 修补定宽的 /ByteRange 字段

2. 加载 PFX 文件并用提供的口令解密。PBES2 接受 AES-128-CBC、AES-192-CBC、AES-256-CBC,配默认 HMAC-SHA-1 或显式 HMAC-SHA-256 / HMAC-SHA-384 / HMAC-SHA-512 PBKDF2 PRF。可选的 PBKDF2 keyLength 必须与所选 AES 密码匹配;旧式 PBE-SHA1-3DES 文件仍受支持,用于较早的证书导出。其他加密 profile 以诊断报告违规 OID

3. 按公钥材料和精确的 RFC 2985 localKeyId 值把 RSA、命名曲线 ECDSA、Ed25519 或 Ed448 私钥与证书配对,再沿颁发者 / 主体名称和 AKI / SKI 扩展保留可用的中间与根证书链

4. 按匹配的密钥选择签名方案,计算所需的文档摘要,并构建 CMS SignedData(RFC 5652)DER 块,含签名者证书、去重后的匹配证书链和已签名属性。RSA 与 ECDSA 签属性摘要;Ed25519 与 Ed448 以 PureEdDSA 模式签名完整的 DER SET OF 属性。Ed25519 用 SHA-512,Ed448 用 512 位输出的 SHAKE256 加 id-shake256-len

5. 把 CMS DER 十六进制编码,校验其适配 AddSignedSignatureField 预留的 /Contents 预算(默认 8 KB 覆盖 1024 / 2048 位 RSA),并注入占位符

6. 把修补后的字节写到输出路径或流

 

成功返回 True。抛出 EHPDFPFXError;输入 PDF 缺少预期占位符或 CMS DER 超出预留的 /Contents 空间时抛出 EHPDFCMSError;RSA 密钥不匹配时抛出 EHPDFRSAError(RSA 密钥不匹配时)

 

典型工作流

 

Doc := THotPDF.Create(nil);

Doc.FileName := 'unsigned.pdf';

Doc.BeginDoc;

Doc.CurrentPage.AddSignedSignatureField(

  'Sig1', Rect(60, 60, 260, 90), 8192,

  'adbe.pkcs7.detached', 'Approved', 'Brussels', '', []);

Doc.EndDoc;

Doc.Free;

THotPDF.SignPDFWithPFX('unsigned.pdf', 'signed.pdf', 'mykey.pfx', 'mypassword');

 

注意事项

便捷重载刻意拒绝包含多组匹配证书与私钥的 PFX。用 HPDFEnumeratePFXIdentities 检视确定性的身份列表及其 LocalKeyID 与 FriendlyName 字段;只需要选定密钥材料时调用 HPDFParsePFXByLocalKeyID

端到端签名时,用 HPDFCMSDefaultSignOptions 初始化 THPDFCMSSignOptions,把选中的精确八位组拷贝到 Options.PFXLocalKeyID,再调用接受这些选项的 HPDFCMSSignPDFStream 重载。选中的叶证书、可用的中间证书与根证书自动嵌入;调用方提供的 Options.AdditionalCertsDER 经精确 DER 去重后合并

 

注记

RSA 与 ECDSA PFX 签名走 HotPDF 原生与 Windows 密码学路径。Ed25519 与 Ed448 PFX 签名需要 OpenSSL 3 libcrypto;直接调用 HPDFCMSSignPDFStream 的调用方可设置 THPDFCMSSignOptions.OpenSSLLibraryPath,便捷重载使用常规的平台库搜索路径

签名算法为 RSA + SHA-256(1.2.840.113549.1.1.1 + 2.16.840.1.101.3.4.2.1)。签名者标识为从 X.509 证书提取的 IssuerAndSerialNumber。encapContentInfo 为分离式(省略 eContent)。已签名属性先按 RFC 5652 第 5.4 节以 DER 字节串升序排序再哈希

 

需要 RFC 3161 时间戳、DSS 字典或文档时间戳签名的 PAdES B-T / B-LT / B-LTA 工作流,生产端辅助方法(AddPAdESSignatureField、AddPAdESDSSCertificate、AddDocumentTimestampSignature)仍然适用;SignPDFWithPFX 本身输出基础 CMS-only 签名(等同 PAdES-B-B)

流重载从不在内存中保留完整的第二份 PDF。它按有界区间哈希修补后的输出,并 seek 修补十六进制 CMS 值而不改变文件长度。定宽十进制偏移支持小于 10,000,000,000 字节的预备 PDF

 

另请参阅: AddSignedSignatureField, PreparePDFForSigning, InsertSignatureHex, AddPAdESSignatureField