PAdES Signature-Policy Validation
HotPDF creates and validates the explicit CMS signature-policy-identifier signed attribute used by PAdES E-EPES signatures
Generate an explicit policy
Set SignaturePolicyOID and the digest of the policy document on THPDFCMSSignOptions, then choose optional structured qualifiers
Options := HPDFCMSDefaultOptions(palExtended_E_EPES);
Options.SignaturePolicyOID := '1.2.3.4.5.1';
Options.SignaturePolicyHash := HPDFCMSDigestBytes(PolicyDocument, cmsdaSHA256);
Options.SignaturePolicyURI := 'https://policies.example/approval-v1';
SetLength(Options.SignaturePolicyQualifiers, 1);
Options.SignaturePolicyQualifiers[0].Kind := cmsqUserNotice;
Options.SignaturePolicyQualifiers[0].ExplicitText := 'Approval policy applies';
CMS := HPDFCMSBuildSignedDataEx(KeyMaterial, DocumentDigest, Options);
SignaturePolicyHashAlgOID defaults to SHA-256 when empty, while SignaturePolicyURI remains a compatibility shortcut for one SPuri qualifier and can be combined with SignaturePolicyQualifiers
The structured qualifier model supports SPuri, SPUserNotice with an optional notice reference and explicit text, and SPDocSpecification identified by an OID or URI
Set SignaturePolicyHashIsUnknown only when the signer does not know the policy hash; HotPDF then emits the ETSI all-zero representation at the selected digest length
Parse and report
HPDFParseCMSSignature exposes the attribute through THPDFSignatureInfo.SignaturePolicy, including its identifier, hash algorithm, hash bytes, unknown-hash flag, qualifiers, and validation status
Known qualifier values are decoded into typed fields, while an unrecognised qualifier retains its OID and raw value DER for application-level handling
HPDFSignatureValidationReportToJSON serializes the same policy and qualifier data with a machine-readable validation status
Pin a required policy
VerifyOptions := THPDFCMSVerifyOptions.Default;
VerifyOptions.RequireSignaturePolicy := True;
VerifyOptions.ExpectedSignaturePolicyOID := '1.2.3.4.5.1';
VerifyOptions.ExpectedSignaturePolicyHash := ExpectedPolicyHash;
VerifyOptions.SignaturePolicyDocument := PolicyDocument;
VerifyOptions.VerifySignaturePolicyDocumentHash := True;
VerifyOptions.RejectUnknownSignaturePolicyHash := True;
Status := HPDFVerifyCMSSignatureEx(Source, ByteRange, CMS,
VerifyOptions, SignatureInfo);
Expected OID and hash fields constrain only the corresponding value, and policy-document verification hashes even an intentionally empty document when VerifySignaturePolicyDocumentHash is true
Missing, mismatched, unsupported, or rejected unknown policies return svSignaturePolicyMismatch and vfcSignaturePolicyMismatch with a precise THPDFSignaturePolicyValidationStatus
Policy checks run before signature-provider, certificate-path, or evidence work and apply only to primary SignerInfo records, so a parent document policy does not constrain counter-signatures
Strictness and bounds
The parser rejects duplicate policy attributes, multiple values, implied-policy NULL, malformed known qualifiers, non-ASCII IA5String values, invalid Unicode, wrong known digest lengths, and collection sizes above the configured implementation limits
PAdES E-EPES requires the explicit policy attribute exactly once and prohibits the PDF Signature Dictionary /Reason entry when that attribute is present; the CMS layer cannot inspect the PDF dictionary, so the PDF-producing workflow must enforce that final constraint
See CMS multiple primary signers, CMS digest-algorithm consistency, and CMS validation reports