TPadesPaddingScheme = (psRsaPss, psRsaPkcs1v15, psEcdsa);
TPadesSignerOptions = record
CertificateThumbprint: string;
PaddingScheme: TPadesPaddingScheme;
class function Default: TPadesSignerOptions; static;
end;
TPadesChainCertArray = array of TBytes;
TPadesResolvedSigner = record
Signer: ICmsSigner;
SignerCertDer: TBytes;
ChainCertDer: TPadesChainCertArray;
end;
TPdfRevocationMode = (prmNone, prmOffline, prmOnlineAllowed,
prmOnlineRequired);
TPdfStringArray = array of string;
TPdfCertificatePathOptions = record
ValidationTime: TDateTime;
RevocationMode: TPdfRevocationMode;
RequiredPolicyOids: TPdfStringArray;
MaxCertificates: Integer;
MaxCertificateBytes: Integer;
MaxFetchBytes: Integer;
MaxPathDepth: Integer;
class function Default: TPdfCertificatePathOptions; static;
end;
TPdfCertificatePathReport = record
Trusted: Boolean;
PathBuilt: Boolean;
PolicyValid: Boolean;
RevocationChecked: Boolean;
PathCertificateCount: Integer;
ErrorCode: Integer;
ErrorMessage: string;
end;
IPdfTrustStore = interface
function LoadTrustAnchors: TPadesChainCertArray;
end;
IPdfValidationFetcher = interface
function Fetch(const Uri: string; MaxBytes: Integer;
out Data: TBytes): Boolean;
end;
IPdfCertificatePathValidator = interface
function Validate(const LeafCertificate: TBytes;
const Intermediates, TrustAnchors: TPadesChainCertArray;
TrustStore: IPdfTrustStore; Fetcher: IPdfValidationFetcher;
const Options: TPdfCertificatePathOptions;
out Report: TPdfCertificatePathReport): Boolean;
end;
IPadesSignerProvider = interface
function BackendName: string;
function Resolve(const Options: TPadesSignerOptions): TPadesResolvedSigner;
end;
TPdfPkcs11Slot = record
SlotID: UInt64;
Description: string;
TokenLabel: string;
TokenPresent: Boolean;
end;
TPdfPkcs11Slots = array of TPdfPkcs11Slot;
TPdfPkcs11Certificate = record
SlotID: UInt64;
ObjectID: TBytes;
LabelText: string;
CertificateDer: TBytes;
Mechanisms: TPdfStringArray;
end;
TPdfPkcs11Certificates = array of TPdfPkcs11Certificate;
IPdfPkcs11SignerProvider = interface(IPadesSignerProvider)
function EnumerateSlots: TPdfPkcs11Slots;
function EnumerateCertificates(SlotID: UInt64): TPdfPkcs11Certificates;
procedure CloseProtectedSessions;
end;
TPdfCmsVerifyStatus = (pcvsUnavailable, pcvsValid, pcvsInvalid,
pcvsUnsupported, pcvsIndeterminate);
TPdfCmsRevocationReason = (pcrrNone, pcrrCertificateRevoked, pcrrCrlExpired,
pcrrCrlNotYetValid, pcrrCrlUnavailable, pcrrCrlSignatureInvalid,
pcrrCrlInvalid, pcrrChainUntrusted, pcrrUnknown, pcrrOcspUnavailable,
pcrrOcspInvalid, pcrrOcspStatusUnknown);
TPdfCmsVerifyStage = (pcvstCryptographicSignature, pcvstChainBuild,
pcvstOnlineRetrieval, pcvstRevocationCheck);
TPdfCmsVerifyCheckpoint = procedure(Stage: TPdfCmsVerifyStage) of object;
TPdfCmsVerifyOptions = record
OnlineRetrieval: Boolean;
CheckRevocation: Boolean;
CollectChainCertificates: Boolean;
UrlRetrievalTimeoutMs: Cardinal;
OnCheckpoint: TPdfCmsVerifyCheckpoint;
CollectSignerDiagnostics: Boolean;
MaxSignerCount: Integer;
class function Default: TPdfCmsVerifyOptions; static;
end;
TPdfCmsSignerVerifyResult = record
SignerIndex: Integer;
SignatureStatus, TrustStatus, RevocationStatus: TPdfCmsVerifyStatus;
SignatureError, TrustError: Cardinal;
SignerCertificate: TBytes;
RevocationReason: TPdfCmsRevocationReason;
RevocationError: Cardinal;
RevocationCertificate: TBytes;
end;
TPdfCmsSignerVerifyResults = array of TPdfCmsSignerVerifyResult;
TPdfCmsVerifyResult = record
SignatureStatus: TPdfCmsVerifyStatus;
TrustStatus: TPdfCmsVerifyStatus;
RevocationStatus: TPdfCmsVerifyStatus;
SignatureError: Cardinal;
TrustError: Cardinal;
SignerCertificate: TBytes;
ChainCertificates: TPadesChainCertArray;
RevocationReason: TPdfCmsRevocationReason;
RevocationError: Cardinal;
RevocationCertificate: TBytes;
SignerResults: TPdfCmsSignerVerifyResults;
SignerDiagnosticsStatus: TPdfCmsVerifyStatus;
SignerCount: Integer;
end;
IPdfCmsVerifier = interface
function BackendName: string;
function VerifyDetached(const CmsDer: TBytes;
Segment1: Pointer; Segment1Length: Cardinal;
Segment2: Pointer; Segment2Length: Cardinal;
const Options: TPdfCmsVerifyOptions): TPdfCmsVerifyResult;
function VerifyAttached(const CmsDer: TBytes;
const Options: TPdfCmsVerifyOptions): TPdfCmsVerifyResult;
end;
procedure ConfigurePadesCmsVerifier(const Verifier: IPdfCmsVerifier);
function PadesCmsVerificationAvailable: Boolean;
function PadesCmsVerificationBackendName: string;
function PadesCryptoAvailable: Boolean;
function PadesCryptoBackendName: string;
function ResolvePadesSigner(const Options: TPadesSignerOptions): TPadesResolvedSigner;
procedure ConfigurePdfCertificatePathValidator(
const Validator: IPdfCertificatePathValidator);
function ValidatePdfCertificatePath(const LeafCertificate: TBytes;
const Intermediates, TrustAnchors: TPadesChainCertArray;
TrustStore: IPdfTrustStore; Fetcher: IPdfValidationFetcher;
const Options: TPdfCertificatePathOptions;
out Report: TPdfCertificatePathReport): Boolean;
procedure ConfigurePadesSignerProvider(const Provider: IPadesSignerProvider);
TPadesSignerResolverProc = function(const Options: TPadesSignerOptions): TPadesResolvedSigner;
PadesSignerResolverOverride: TPadesSignerResolverProc;
PdfCertificatePathValidator: IPdfCertificatePathValidator;
PadesSignerProvider: IPadesSignerProvider;
PadesCmsVerifier: IPdfCmsVerifier;
FPdfCrypto 是 PAdES 签名栈的统一入口。PadesCryptoAvailable 报告签名材料及后端是否可用,PadesCryptoBackendName 标识所选后端;Windows 默认使用 Cryptography Next Generation,其他平台从 FPdfCryptoSsl 解析明确配置的 OpenSSL 私钥和证书
ResolvePadesSigner 接收一个证书指纹和一种填充方案,返回一个完全填充的 TPadesResolvedSigner:执行私钥运算的 ICmsSigner 实现、签名者证书 DER,以及签发链证书。该结果可直接传递给 FPdfCms.BuildSignedData
自定义集成可以注册 IPadesSignerProvider(包括枚举令牌槽位和证书的 IPdfPkcs11SignerProvider),或使用 PadesSignerResolverOverride 作为确定性的解析器接缝
证书路径验证基于提供方且有预算约束:调用方配置 IPdfCertificatePathValidator,可选地提供显式信任锚、IPdfTrustStore 和 IPdfValidationFetcher,然后检查 TPdfCertificatePathReport
| 函数 | 说明 |
|---|---|
PadesCryptoAvailable | 当当前平台上存在可用于 PAdES 签名的加密后端时返回 True |
PadesCryptoBackendName | 返回活动加密后端的显示名称 |
ResolvePadesSigner | 将证书指纹和填充方案解析为签名器、签名者证书和证书链 |
ConfigurePdfCertificatePathValidator | 设置或清除 ValidatePdfCertificatePath 使用的进程级 IPdfCertificatePathValidator |
ValidatePdfCertificatePath | 在强制证书数量、大小、获取和路径深度预算之后,针对中间证书以及显式与信任存储合并的锚点验证叶子证书 |
ConfigurePadesSignerProvider | 设置或清除在平台后端之前使用的进程级签名器提供方 |
ConfigurePadesCmsVerifier | 安装 PAdES 验证器使用的 CMS 验证后端;清除配置后,Windows 恢复使用 Windows CryptoAPI。其他平台须明确调用 ConfigureSslCmsVerifier 或 ConfigureKeychainCmsVerifier |
PadesCmsVerificationAvailable | 当本构建中存在能验证 CMS 的后端(无论是注册的还是内置的)时返回 True |
PadesCmsVerificationBackendName | 返回当前活动验证后端的显示名称,没有则返回空字符串 |
| 接口成员 | 说明 |
|---|---|
IPdfTrustStore.LoadTrustAnchors | 返回受配置证书预算约束的额外 DER 编码信任锚 |
IPdfValidationFetcher.Fetch | 从 Uri 获取验证材料且不超过 MaxBytes |
IPdfCertificatePathValidator.Validate | 构建并评估证书路径,填充 TPdfCertificatePathReport |
IPadesSignerProvider.BackendName | 返回由 PadesCryptoBackendName 公开的提供方显示名称 |
IPadesSignerProvider.Resolve | 为提供的 TPadesSignerOptions 返回完整的签名器材料 |
IPdfPkcs11SignerProvider.EnumerateSlots | 返回可用的 PKCS#11 槽位及令牌存在元数据 |
IPdfPkcs11SignerProvider.EnumerateCertificates | 返回一个 PKCS#11 槽位中可见的证书和签名机制 |
IPdfPkcs11SignerProvider.CloseProtectedSessions | 关闭由提供方拥有的受保护或已认证 PKCS#11 会话 |
IPdfCmsVerifier.BackendName | 返回 PadesCmsVerificationBackendName 所报告的验证后端显示名称 |
IPdfCmsVerifier.VerifyDetached | 验证 PDF 签名;签名的实际内容是 /Contents 缺口两侧的两段字节范围 |
IPdfCmsVerifier.VerifyAttached | 验证时间戳令牌;令牌自带内容,不需要分离的内容段 |
| 类型 | 说明 |
|---|---|
EPadesCrypto | 加密后端失败的基异常 |
EPadesCryptoUnavailable | 当所需的签名器后端或证书路径验证器未配置时抛出 |
TPadesPaddingScheme | psRsaPss、psRsaPkcs1v15 或 psEcdsa |
TPadesSignerOptions | CertificateThumbprint 选择证书,PaddingScheme 选择签名方案;Default 使用空指纹和 psRsaPss |
TPadesChainCertArray | DER 编码链证书的动态数组 |
TPadesResolvedSigner | Signer、SignerCertDer 和 ChainCertDer 捆绑已解析的签名器和证书材料 |
TPdfRevocationMode | prmNone、prmOffline、prmOnlineAllowed 或 prmOnlineRequired |
TPdfStringArray | 用于策略 OID 和提供方机制名称的动态字符串数组 |
TPdfCertificatePathOptions | ValidationTime、RevocationMode、RequiredPolicyOids、MaxCertificates、MaxCertificateBytes、MaxFetchBytes 和 MaxPathDepth 控制验证和资源预算;Default 选择离线吊销检查,限制为 64 张证书、每张证书 4 MiB、获取数据 16 MiB 和路径深度 16 |
TPdfCertificatePathReport | Trusted、PathBuilt、PolicyValid、RevocationChecked、PathCertificateCount、ErrorCode 和 ErrorMessage 报告验证结果 |
TPdfPkcs11Slot | SlotID、Description、TokenLabel 和 TokenPresent 描述一个 PKCS#11 槽位 |
TPdfPkcs11Slots | TPdfPkcs11Slot 记录的动态数组 |
TPdfPkcs11Certificate | SlotID、ObjectID、LabelText、CertificateDer 和 Mechanisms 描述一个令牌证书 |
TPdfPkcs11Certificates | TPdfPkcs11Certificate 记录的动态数组 |
TPadesSignerResolverProc | 用于 PadesSignerResolverOverride 注入变量的函数指针类型 |
TPdfCmsVerifyStatus | pcvsUnavailable、pcvsValid、pcvsInvalid、pcvsUnsupported 或 pcvsIndeterminate |
TPdfCmsRevocationReason | pcrrNone、pcrrCertificateRevoked、pcrrCrlExpired、pcrrCrlNotYetValid、pcrrCrlUnavailable、pcrrCrlSignatureInvalid、pcrrCrlInvalid、pcrrChainUntrusted、pcrrUnknown、pcrrOcspUnavailable、pcrrOcspInvalid 或 pcrrOcspStatusUnknown 独立于验证状态说明吊销证据 |
TPdfCmsVerifyStage | pcvstCryptographicSignature、pcvstChainBuild、pcvstOnlineRetrieval 或 pcvstRevocationCheck |
TPdfCmsVerifyCheckpoint | 对象方法形式的回调,随验证推进逐个接收 TPdfCmsVerifyStage |
TPdfCmsVerifyOptions | OnlineRetrieval、CheckRevocation、CollectChainCertificates、UrlRetrievalTimeoutMs 和 OnCheckpoint 控制验证;CollectSignerDiagnostics 请求每签名者快照,MaxSignerCount 限制数量。Default 关闭检索、吊销和签名者诊断,检索预算为 15 秒,签名者快照上限为 64 |
TPdfCmsSignerVerifyResult | SignerIndex 标识编码中的 SignerInfo 顺序;签名、信任、吊销状态和原生错误分别描述该签名者。SignerCertificate 是其 DER 证书,RevocationCertificate 则在后端可提供时标识所捕获吊销错误关联的证书 |
TPdfCmsSignerVerifyResults | 带数量上限的签名者快照动态数组 |
TPdfCmsVerifyResult | 汇总签名、信任和吊销状态各自独立。记录还返回 SignatureError、TrustError、SignerCertificate、ChainCertificates、RevocationReason、RevocationError、RevocationCertificate、SignerResults、SignerDiagnosticsStatus 和 SignerCount |
公开选项和结果记录已扩展,升级时须重新编译使用方。自定义验证器应通过 Default(TPdfCmsVerifyResult) 初始化托管结果记录,不支持的快照字段保持不可用;不要用 FillChar 清空含字符串或动态数组的活动记录
RevocationReason 和 RevocationError 从 IPdfCmsVerifier.VerifyDetached 或 VerifyAttached 返回的 TPdfCmsVerifyResult 中读取。PAdES 信任验证会把它们保留为 RevocationReason 和 NativeRevocationError;时间戳令牌另有独立的 TimeStampRevocationReason 和 NativeTimeStampRevocationError 字段,证据报告会同时包含这两对
RevocationError 是后端相关的原生验证代码,0 表示没有捕获到原生诊断。OpenSSL 使用 X509_V_ERR_* 错误空间。Windows 保留证书 CERT_REVOCATION_INFO.dwRevocationResult 中的原始 DWORD,若其吊销链调用失败则保留 GetLastError 的返回值;它既不是统一的 HRESULT 错误空间,也不是聚合的链信任位掩码
OpenSSL 区分已确认吊销、过期/不可用/无效 CRL 证据,以及不可用/无效/未知 OCSP 证据。Windows 报告已确认吊销、不受信任的链或未知原生失败。macOS 验证器分别评估签名完整性、Basic X.509 信任和吊销,返回原生 Security.framework 错误,不把每种平台失败都映射成 CRL 或 OCSP 分类
RevocationCertificate 可能标识已吊销的中间证书,而非 CMS 签名者证书;后端无法捕获该证书时为空。OpenSSL 可以收集它,当前 macOS 后端则保持为空
pcrrNone 或 0 错误码都不能证明吊销已检查或已通过;判断结果请始终看 RevocationStatus
设置 CollectSignerDiagnostics=True,可查看 SignerResults 中数量受限的快照。SignerCount 在确定后表示编码中的 SignerInfo 数量,零表示尚未确定
SignerDiagnosticsStatus=pcvsValid 表示请求的快照已完整收集,包括无效签名快照,并不代表所有签名通过。pcvsUnavailable 表示收集已关闭或不受支持,pcvsIndeterminate 表示后端未能在解析或资源限制内完成所请求收集
OpenSSL 和原生 macOS 实现均最多收集 64 个签名者。OpenSSL 另将诊断 CMS 输入限制为 4 MiB,累计诊断输入/输出工作量限制为 64 MiB;macOS 返回证书材料限制为每证书 4 MiB、总计 64 MiB。更低的 MaxSignerCount 会进一步降低调用方请求数量
签名者快照复用配置证据和汇总验证时检索的证据。OpenSSL 不会为每个诊断快照再次联网检索,汇总检索不完整也不能转化为成功的离线吊销快照
PadesSignerResolverOverride 优先,其次是明确注册的 IPadesSignerProvider,最后是平台默认。非 Windows 默认须调用 ConfigureSslSigningCredentials;仅有 libcrypto 不会提供私钥或证书
OpenSSL 默认实现拒绝非空 CertificateThumbprint,因为证书已由显式配置选定。应用选择该提供器时,仍可通过 ConfigureKeychainSignerProvider 使用 Keychain 签名
| 变量 | 说明 |
|---|---|
PadesSignerResolverOverride | 在已注册提供方和平台提供方之前求值的可选解析器回调 |
PadesCmsVerifier | 当前 CMS 验证后端,通常通过 ConfigurePadesCmsVerifier 赋值 |
PdfCertificatePathValidator | 当前证书路径验证器,通常通过 ConfigurePdfCertificatePathValidator 赋值 |
PadesSignerProvider | 当前签名器提供方,通常通过 ConfigurePadesSignerProvider 赋值 |