Verify CMS SignedData (the RFC 5652 verdict: signers, chains, time-stamps, revocation)
verify_cmsValidates CMS SignedData signatures and every signer's certificate chain, timestamp, and revocation status offline against your trust anchors, returning a clear valid:false verdict with reasons.
Instructions
The one-call verdict on a CMS SignedData (a .p7s, an S/MIME body, a PDF /Contents): for EVERY signer, the signed attributes (contentType, messageDigest, ESS signing-certificate, CMSAlgorithmProtection), the content digest (attached, or content / contentDigest for a detached signature — a detached signature without its content is NOT valid), the signature, the certificate's chain through candidates and the embedded certificates to one of YOUR trustAnchors at at (RFC 5280 §6, purposes along the path), every counter time-stamp (RFC 3161, verified like verify_timestamp), and revocation from the CRL / OCSP bytes YOU supply plus those the message carries (requireRevocation:true demands evidence; this server never fetches). atTimeStamp:true is long-term validation: a signer's chain is judged at its verified time-stamp instead of at. requireSigningCertificate / requireAlgorithmProtection enforce the CAdES / RFC 8933 profile. A negative verdict is valid:false + reasons[] (PKI_REASON_* codes, per signer too; intact tells unaltered from untrusted) — never isError; isError is for inputs the engine refuses (content given for an attached message, both content and contentDigest). Pin at for a reproducible, cacheable verdict. Token-frugal: verbosity:'summary' (valid, reasonCodes, per-signer codes).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| at | No | The instant the verdict is evaluated at. An ISO 8601 date-time (UTC unless zoned; e.g. 2027-01-01T00:00:00Z), epoch milliseconds as digits, or 'now'. Omitted: PKINATIVE_MCP_AT when the operator pinned it, else the wall clock (a clock-dependent result is never cached). | |
| crls | No | CRLs (DER or X509 CRL PEM) for offline revocation, added to those the message carries. Optional; this server never fetches a CRL. | |
| fields | No | Dot-paths to keep after verbosity (arrays map over elements); unmatched paths land in _meta.unmatchedFields. | |
| limits | No | Raise pkinative's 22 named security bounds for this call (trusted input only; absent keys keep the engine defaults). A value above an operator ceiling (PKINATIVE_MCP_MAX_INPUT_BYTES, PKINATIVE_MCP_MAX_KDF_ITERATIONS, PKINATIVE_MCP_MAX_PATHS_EXPLORED) is LIMIT_CEILING_EXCEEDED; describe_engine lists the defaults and the ceilings. | |
| strict | No | Escalate the first engine warning to a PKI_STRICT_DIAGNOSTIC error instead of listing it in diagnostics[]. | |
| content | No | The detached content (required for a detached signature; refused for an attached one): exactly one of text / base64 / path. | |
| pemMode | No | 'strict' (RFC 7468 exactly, default) or 'lax' (tolerates whitespace, line length and RFC 1421 headers). | strict |
| purposes | No | Extended key usages every signer's chain must permit (emailProtection for S/MIME): serverAuth, clientAuth, codeSigning, emailProtection, timeStamping, ocspSigning, any, or a dotted OID. | |
| allowSha1 | No | Accept or produce SHA-1 signatures (legacy material you already trust). Default false: refused with PKI_CRYPTO_ALGORITHM_REFUSED on read, VALIDATION_ERROR on write. | |
| verbosity | No | 'summary' keeps the scalar fields only (token-frugal). | full |
| candidates | No | Untrusted intermediate certificates the path may use (every PEM block of every item is taken). Optional; the certificates embedded in a CMS message are also candidates. | |
| signedData | Yes | The CMS SignedData to judge (CMS / PKCS7 PEM, or DER: .p7s .p7m): exactly one of pem / derBase64 / path. | |
| atTimeStamp | No | Judge each signer's chain at the time its own VERIFIED counter time-stamp proves (long-term validation) instead of `at`; a signer without a valid time-stamp is still judged at `at`, and the TSA's chain always is. | |
| trustAnchors | Yes | Trust anchors (root certificates you trust) (every PEM block of every item is taken). At least one is required: a verdict is relative to the anchors you name. | |
| contentDigest | No | The detached content's digest (computed with the signer's digest algorithm) instead of the content — the PDF /ByteRange case. Exclusive with content. Hexadecimal (an 0x prefix, colons and spaces are tolerated). | |
| encodingRules | No | 'der' (strict X.690 DER, default) or 'ber' (indefinite / non-minimal lengths and constructed strings, as legacy CMS producers write). | der |
| ocspResponses | No | OCSP responses (DER), added to those the message carries. Optional; this server never queries a responder. | |
| allowTrailingData | No | Ignore bytes after the ContentInfo (the zero padding of a PDF /Contents). Default false: trailing bytes are PKI_ASN1_TRAILING_DATA. | |
| requireRevocation | No | Require fresh revocation evidence for the end-entity certificate (PKI_REASON_REVOCATION_UNKNOWN otherwise — the engine demands it for the leaf; an intermediate is judged from the evidence you pass); default false = revocation is checked when evidence is given. | |
| requireSigningCertificate | No | Require every signer to name its certificate in an ESS signing-certificate attribute (CAdES / PAdES). | |
| requireAlgorithmProtection | No | Require every signer to carry CMSAlgorithmProtection (RFC 6211). |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| valid | No | At least one signer and EVERY signer valid. false is a negative verdict (reasons[]), never an error. | |
| reasons | No | Why the verdict is negative (empty when valid): the engine PKI_REASON_* codes, each with the standard it cites and the path of the offending element. A reason is returned, never thrown. | |
| signers | No | One verdict per signer, in encoded order. | |
| atTimeStamp | No | ||
| diagnostics | No | Non-fatal concerns the engine raised (PKI_DIAG_*, de-duplicated, at most 200; explain_code explains one). | |
| evaluatedAt | No | The ISO instant the chains were judged at — re-pass it as `at` to reproduce the verdict. | |
| reasonCodes | No | ||
| signerCount | No | ||
| diagnosticCount | No | ||
| diagnosticCounts | No | Occurrences per diagnostic code. | |
| evaluatedAtSource | No | ||
| diagnosticsTruncated | No | true when distinct diagnostics beyond the 200 listed were dropped. | |
| signatureVerifications | No | Signature verifications performed, chains and time-stamps included. |