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