增量 PFX 签名 job
sign 操作支持经过验证的增量 profile,精确保留原始 PDF 修订与每个既有密码学签名,同时返回单独签名的产物
选择 profile
{"schemaVersion":1,"type":"sign","profile":"pfx-incremental-document",
"pfxFile":"C:/keys/signer.pfx","pfxPassword":"password",
"fieldName":"ApprovalTwo","existingField":true,
"budget":{"memoryBytes":268435456,"outputBytes":134217728,
"resultBytes":16777216,"timeMilliseconds":60000,
"objectCount":1000000,"pageCount":1024}}
默认的 pfx-unsigned-document profile 保留原始行为,接受没有任何签名字段的源;它使用 page、x1、y1、x2 与 y2 创建新字段,并在发布前恢复源对象图
pfx-incremental-document 选择新 profile;省略 profile 时 incremental: true 是等价选择器,与显式的不同 profile 冲突
existingField: true 填充具名的空签名字段而不添加另一个字段;否则操作创建新字段,page 与矩形标识其控件
fieldName 默认为 Signature1,接受 1 到 1024 个 UTF-8 字节;existingField 要求增量 profile、匹配的签名字段以及缺失或 null 的 V 值
只读 Ff 位 1 以及格式错误或超出范围的整数标志在准备前被拒绝;继承的 SV 与 Lock 字典以唯一的语义 PDF 名称与有界父级遍历解析
seed 值与字段锁定
digestMethod 选择真实的 SHA256、SHA384 或 SHA512 CMS 摘要;SHA256 是默认值,cades: true 选择 ETSI.CAdES.detached 并包含绑定真实签名证书的 signing-certificate-v2 属性
reason、location 与 contactName 是写成 PDF Unicode 文本字符串的 UTF-8 JSON 字符串;必需的 seed reason 比较其 Unicode 值,包括那个要求省略 reason 的特殊单点值
必需的 SV 约束检查真实 handler、CMS SubFilter、受支持的签名版本、摘要、reason、认证权限、法律声明与 LockDocument 模式;必需的时间戳使用 Windows 签名时间戳所述的应用传输与显式信任工作流,必需的已签名吊销证据使用 已认证的 CRL 与 OCSP 签名,必需的具名外观使用 真实生成的签名外观预设
必需的 SVCert 属性在签名之前验证真实的 PFX 叶子证书与所含颁发者链、允许的证书字节、证书策略 OID、密钥用法位与 Unicode 主体 DN 属性
credentialSourceURL 为必需的 SVCert URL 提供应用声明的凭据来源;库比较声明的 URL 与受支持的 URLType,不会打开该端点或认证传输身份
All、Include 与 Exclude 字段锁定写成间接 SigFieldLock 字典以及绑定到文档 Catalog 的匹配 FieldMDP 引用;字段名使用 PDF Unicode 文本字符串,在加密文档中保持加密
已签名的 Lock P 值使用原始签名字段策略限制后续修订,独立于任何 DocMDP 权限;被允许的第二个签名精确保留前一修订与 CMS,而锁定的字段或 P1 变更在发布前被拒绝
策略查找对 PDF 名称转义恰好解码一次,包括继承的 Parent 名称;含重复语义名称以及无效或循环父级的字典在发布前被拒绝,有效的转义名称保留其源字节
contentsBytes 默认 16384,接受 1024 到 1048576;reason、location 与 contactName 填充新签名字典
认证与法律声明
certificationPermission 默认为 0,用于批准签名;1、2 或 3 创建带所请求 DocMDP 权限的认证签名,把 Catalog Perms DocMDP 绑定到真实的间接签名字典,并保留任何独立 FieldMDP 变换
认证必须是第一个签名,文档只能包含一个认证签名;畸变的 Catalog 权限、未解析引用以及没有原始签名字段绑定的 DocMDP 值都被拒绝
legalAttestation 是认证签名的可选 Unicode 字符串,写入 Catalog Legal Attestation;必需的 SV LegalAttestation 列表必须包含所选文本,而空的必需列表要求省略
既有 P2 与 P3 认证签名在字段锁定与修订策略允许时允许后续批准签名;P1 签名与锁定字段在二进制发布前拒绝变更
源契约
增量 job profile 接受保留的原始源(包括受支持的加密 PDF)与未修改的已加载对象图;源加密时在 sign 操作中提供 password,与 pfxPassword 分开
源密码认证独立的原始快照,初始化原始加密上下文并重新打开已签名候选;所得增量修订保留原始密文前缀、安全字典与永久文档 ID
解密可能在内部把对象标记为 dirty 或从已解密对象图中移除安全字典;操作将这些状态与有界对象序列化对照全新认证的源基线,同时拒绝真实的对象图变更与所有已刷新对象状态
对用户密码而言,既有签名字段要求表单填充或注释权限,新签名控件要求注释权限;已认证的所有者密码可授权任一操作,仍受既有签名策略约束
SaveLoadedDocumentToStream 可能改变序列化状态;对已保存或已编辑的对象图签名时,把保存的字节重新加载到新句柄并签署该修订
在句柄生命周期内保持原始源存储稳定;文件 job 在加载与准备快照期间拒绝写共享
原始句柄保留其字段计数、既有字段身份、表单值、源字节以及先前的启动与解码设置;每次签名成功都返回 documentUpdated: false,签名失败后句柄仍可用于查询、保存或后续有效请求
文件 job 拒绝等于或别名为输入文件的输出路径,包括硬链接;直接流 API 拒绝可识别的源流与源文件别名,调用方还必须让不透明的 callback 输出存储与输入存储相互区分
准备与验证
操作把原始源字节复制到独占创建的临时快照,打开独立的增量克隆,通过有界的 SaveIncrementalUpdate 追加占位符,并通过原生 PFX 流签名器填充 detached CMS
PFX 从大小预检到签名保持打开并拒绝写共享;临时文件使用 CREATE_NEW,只有操作自身创建它们时才会移除
已签名候选必须包含精确的源字节前缀与预期的表单及签名字段计数;新签名必须在其所选字段中通过验证,每个先前已填充的签名必须仍能通过验证,每个旧签名的修订分析必须接受 DocMDP、FieldMDP、使用权限与身份约束
未填充的旧字段被保留,不计入 preservedSignatures;格式错误、无效或违反策略的既有签名会在二进制发布前导致拒绝
既有签名验证对照已签名字节与原生修订策略检查 CMS 完整性;新签名请求时间戳时,其响应在发布前单独验证显式 TSA 信任与配置的吊销证据
预算与发布
有效输出上限是 min(outputBytes, memoryBytes / 8),包含完整源前缀、追加对象、xref 与签名预留;effectiveOutputLimit 报告实际应用的上限
未签名候选与已签名输出分别受该上限约束,PFX 字节上限为 memoryBytes / 8,源基线、克隆与候选解码预算分别以 memoryBytes / 8 为上限,文件溢出阈值不超过 1 MiB
这些是操作与缓冲预算,不是严格的进程 RSS 保证;密码学、对象元数据、修订分析以及调用方已加载的源可能需要额外的常驻内存
取消与耗时检查适用于源复制、增量序列化与复制、候选读取、签名验证读取、修订分析读取与 callback 发布;粘性的原生流失败在 job 边界保留其预算或取消类别
二进制输出在第一个输出 callback 之前暂存并验证,结果 JSON 大小在二进制发布前检查;callback 输出本身不是原子的,因此失败的二进制或结果 callback 可能留下调用方必须丢弃的字节
文件 job 写入同目录的自有候选,刷新它,关闭源与输出句柄,验证成功后原子替换一个不同的目标;失败时保留既有目标
成功时返回 mediaType: application/pdf、fieldName、profile、incremental、existingField、certificationPermission、revocationInfo、appearanceProfile、preservedSignatures、effectiveOutputLimit、outputBytes 与 documentUpdated: false
重放验收
$env:HOTPDF_SUPPRESS_AUTO_LAUNCH = '1'
./Tests/CABI/Run-IncrementalSigningAcceptance.ps1 -BuildDLL -CheckFPC
runner 通过注册表 RootDir 发现 RAD Studio,接受 RADStudioRoot 与 PythonExecutable 覆盖,选择 CheckFPC 时使用配置的 FPC 工具链;FPCOnly 只重放那些原生目标,OpenSSLWin32Library 与 OpenSSLWin64Library 为每个架构选择匹配的运行时库
非 GUI runner 使用部分 callback 检查 Win32 与 Win64 原生 API 及真实 C ABI DLL,覆盖既有空字段、先前签名、必需 seed 值、真实的 SHA384 与 SHA512 CAdES、Unicode 元数据、被允许与被锁定的第二个签名、真实 PFX 证书属性、AES-128 与 AES-256 字段锁定变换、权限限制与所有者凭据、错误密码、dirty 已解密对象图、精确加密源快照、加密原地写入器恢复、真实 DocMDP P1 与 P2 CMS fixture、预算、取消、callback 失败以及失败后的源复用
独立的 pypdf、MuPDF 与 OpenSSL 检查证明精确的先前前缀与字节范围、未变更的加密与永久 ID、可搜索的原始文本、有效的新旧 CMS 值、签名 Contents 加密豁免以及对已修改签名内容的拒绝;independent-proof.json 记录字节范围与证明结果
相关主题
文档操作、CopyLoadedSourceToStream、SaveIncrementalUpdate、EHPDFIncrementalOutputBudget