PDFium Delphi Component Docs

FPdfCrypto 单元

单元: FPdfCrypto
面向平台后端、PKCS#11 集成、信任存储、吊销获取器和有界路径验证的 PAdES 签名器提供方与证书验证门面

语法

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当所需的签名器后端或证书路径验证器未配置时抛出
TPadesPaddingSchemepsRsaPss、psRsaPkcs1v15 或 psEcdsa
TPadesSignerOptionsCertificateThumbprint 选择证书,PaddingScheme 选择签名方案;Default 使用空指纹和 psRsaPss
TPadesChainCertArrayDER 编码链证书的动态数组
TPadesResolvedSignerSigner、SignerCertDer 和 ChainCertDer 捆绑已解析的签名器和证书材料
TPdfRevocationModeprmNone、prmOffline、prmOnlineAllowed 或 prmOnlineRequired
TPdfStringArray用于策略 OID 和提供方机制名称的动态字符串数组
TPdfCertificatePathOptionsValidationTime、RevocationMode、RequiredPolicyOids、MaxCertificates、MaxCertificateBytes、MaxFetchBytes 和 MaxPathDepth 控制验证和资源预算;Default 选择离线吊销检查,限制为 64 张证书、每张证书 4 MiB、获取数据 16 MiB 和路径深度 16
TPdfCertificatePathReportTrusted、PathBuilt、PolicyValid、RevocationChecked、PathCertificateCount、ErrorCode 和 ErrorMessage 报告验证结果
TPdfPkcs11SlotSlotID、Description、TokenLabel 和 TokenPresent 描述一个 PKCS#11 槽位
TPdfPkcs11SlotsTPdfPkcs11Slot 记录的动态数组
TPdfPkcs11CertificateSlotID、ObjectID、LabelText、CertificateDer 和 Mechanisms 描述一个令牌证书
TPdfPkcs11CertificatesTPdfPkcs11Certificate 记录的动态数组
TPadesSignerResolverProc用于 PadesSignerResolverOverride 注入变量的函数指针类型
TPdfCmsVerifyStatuspcvsUnavailable、pcvsValid、pcvsInvalid、pcvsUnsupported 或 pcvsIndeterminate
TPdfCmsRevocationReasonpcrrNone、pcrrCertificateRevoked、pcrrCrlExpired、pcrrCrlNotYetValid、pcrrCrlUnavailable、pcrrCrlSignatureInvalid、pcrrCrlInvalid、pcrrChainUntrusted、pcrrUnknown、pcrrOcspUnavailable、pcrrOcspInvalid 或 pcrrOcspStatusUnknown 独立于验证状态说明吊销证据
TPdfCmsVerifyStagepcvstCryptographicSignature、pcvstChainBuild、pcvstOnlineRetrieval 或 pcvstRevocationCheck
TPdfCmsVerifyCheckpoint对象方法形式的回调,随验证推进逐个接收 TPdfCmsVerifyStage
TPdfCmsVerifyOptionsOnlineRetrieval、CheckRevocation、CollectChainCertificates、UrlRetrievalTimeoutMs 和 OnCheckpoint 控制验证;CollectSignerDiagnostics 请求每签名者快照,MaxSignerCount 限制数量。Default 关闭检索、吊销和签名者诊断,检索预算为 15 秒,签名者快照上限为 64
TPdfCmsSignerVerifyResultSignerIndex 标识编码中的 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 赋值

参见

FPdfCms, FPdfCryptoWin, FPdfCryptoSsl, FPdfCryptoMac, FPdfCryptoOcsp, FPdfTsa, TPdf.SignPades