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로 곧바로 전달됩니다
사용자 지정 통합은 토큰 슬롯과 인증서를 열거하는 IPdfPkcs11SignerProvider를 포함한 IPadesSignerProvider를 등록하거나, 결정론적 해석자 이음새로 PadesSignerResolverOverride를 사용할 수 있습니다
인증서 경로 검증은 공급자 기반이며 예산이 적용됩니다. 호출자는 IPdfCertificatePathValidator를 구성하고 선택적으로 명시적 신뢰 앵커, IPdfTrustStore, IPdfValidationFetcher를 제공한 뒤 TPdfCertificatePathReport를 점검합니다
| 함수 | 설명 |
|---|---|
PadesCryptoAvailable | 현재 플랫폼에서 PAdES 서명에 사용할 크립토 백엔드가 있으면 True를 반환합니다 |
PadesCryptoBackendName | 활성 크립토 백엔드의 표시 이름을 반환합니다 |
ResolvePadesSigner | 인증서 썸프린트와 패딩 방식을 서명자, 서명자 인증서, 체인으로 해석합니다 |
ConfigurePdfCertificatePathValidator | ValidatePdfCertificatePath가 사용하는 프로세스 전체 IPdfCertificatePathValidator를 설정하거나 지웁니다 |
ValidatePdfCertificatePath | 인증서 수, 크기, fetch, 경로 깊이 예산을 강제한 뒤 리프 인증서를 중간 인증서 및 결합된 명시적·신뢰 저장소 앵커와 대조해 검증합니다 |
ConfigurePadesSignerProvider | 플랫폼 백엔드보다 먼저 사용되는 프로세스 전체 서명자 공급자를 설정하거나 지웁니다 |
ConfigurePadesCmsVerifier | PAdES 검증기가 사용할 CMS 검증 백엔드를 등록합니다. 설정을 지우면 Windows에서 Windows CryptoAPI로 돌아갑니다. 다른 플랫폼은 ConfigureSslCmsVerifier나 ConfigureKeychainCmsVerifier를 명시적으로 호출해야 합니다 |
PadesCmsVerificationAvailable | 등록되었든 내장이든 이 빌드에서 CMS를 검증할 수 있는 백엔드가 있으면 True를 반환합니다 |
PadesCmsVerificationBackendName | 활성 검증 백엔드의 표시 이름을 반환하고 없으면 빈 문자열을 반환합니다 |
| 인터페이스 멤버 | 설명 |
|---|---|
IPdfTrustStore.LoadTrustAnchors | 구성된 인증서 예산의 적용을 받아 추가 DER 인코딩 신뢰 앵커를 반환합니다 |
IPdfValidationFetcher.Fetch | MaxBytes를 초과하지 않으면서 Uri에서 검증 자료를 가져옵니다 |
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 | 타임스탬프 토큰을 검증합니다. 토큰은 자체 콘텐츠를 담고 있어 detached 세그먼트가 필요 없습니다 |
| 타입 | 설명 |
|---|---|
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 주입 var을 위한 함수 포인터 형식 |
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)로 초기화하고 지원하지 않는 스냅샷 필드는 unavailable로 두어야 합니다. 문자열이나 동적 배열을 가진 살아 있는 레코드를 FillChar로 지우지 마세요
IPdfCmsVerifier.VerifyDetached나 VerifyAttached가 반환하는 TPdfCmsVerifyResult에서 RevocationReason과 RevocationError를 읽습니다. PAdES trust 검증은 이를 RevocationReason과 NativeRevocationError로 보존하고, timestamp 토큰용으로는 별도의 TimeStampRevocationReason과 NativeTimeStampRevocationError 필드를 둡니다. evidence 리포트에는 두 쌍이 모두 들어갑니다
RevocationError는 백엔드별 네이티브 검증 코드이며 0은 잡아낸 네이티브 진단이 없다는 뜻입니다. OpenSSL은 X509_V_ERR_* 오류 공간을 씁니다. Windows는 인증서의 CERT_REVOCATION_INFO.dwRevocationResult에서 나온 raw DWORD를, 폐기 체인 호출이 실패하면 GetLastError 값을 그대로 유지합니다. 이는 균일한 HRESULT 오류 공간도, 집합 체인 신뢰 비트마스크도 아닙니다
OpenSSL은 확인된 폐지와 만료/사용 불가/잘못된 CRL, 사용 불가/잘못된/unknown OCSP를 구분합니다. Windows는 확인된 폐지, 신뢰하지 않는 체인, 알 수 없는 네이티브 실패를 보고합니다. macOS 검증기는 서명 무결성, Basic X.509 신뢰, 폐지를 따로 평가하고 모든 플랫폼 오류를 CRL/OCSP 분류로 바꾸지 않고 Security.framework 오류를 반환합니다
RevocationCertificate는 CMS 서명자 대신 폐지된 중간 인증서일 수도 있으며 수집할 수 없는 백엔드에서는 비어 있습니다. OpenSSL은 수집할 수 있지만 현재 macOS 백엔드는 비워 둡니다
pcrrNone도 0 오류도 폐기 검사가 수행되었거나 성공했다는 증거가 아닙니다. 항상 RevocationStatus를 확인하세요
CollectSignerDiagnostics=True로 설정하면 SignerResults에서 상한이 있는 스냅샷을 볼 수 있습니다. SignerCount는 확인된 인코딩 SignerInfo 수이며 0은 수를 확인하지 못했다는 뜻입니다
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를 거부합니다. 애플리케이션이 Keychain 프로바이더를 선택하면 ConfigureKeychainSignerProvider로 계속 사용할 수 있습니다
| 변수 | 설명 |
|---|---|
PadesSignerResolverOverride | 등록된 공급자와 플랫폼 공급자보다 먼저 평가되는 선택적 해석자 콜백 |
PadesCmsVerifier | 현재 CMS 검증 백엔드이며 보통 ConfigurePadesCmsVerifier로 할당됩니다 |
PdfCertificatePathValidator | 현재 인증서 경로 검증기이며 보통 ConfigurePdfCertificatePathValidator로 할당됩니다 |
PadesSignerProvider | 현재 서명자 공급자이며 보통 ConfigurePadesSignerProvider로 할당됩니다 |