Standards & Profiles
PAdES baseline levels, LTV/DSS with CRL and OCSP, RFC-3161 timestamps, and document timestamps — the standards Mudrit produces
Mudrit produces signatures to standards-grade profiles: PAdES baseline levels (ETSI EN 319 142), LTV via the document security store, RFC-3161 signature timestamps, and standalone document timestamps. This page explains what each standard is and what Mudrit emits for it.
Validation is external
Mudrit produces standards-conformant signed PDFs; it does not ship a signature-verification API. Validate the output externally — Adobe Acrobat / Reader or pyHanko.
The SubFilter: legacy vs. PAdES
Every signature carries a /SubFilter that names its format. Mudrit writes one of two:
| SubFilter | Profile | When |
|---|---|---|
adbe.pkcs7.detached | Legacy Adobe CMS | The default (no .pades(…)) |
ETSI.CAdES.detached | PAdES / CAdES | Selecting any PadesLevel |
Choosing a PAdES level switches the SubFilter to ETSI.CAdES.detached and adds the ESS
signing-certificate-v2 signed attribute (RFC 5035) that binds the signature to the exact signing
certificate.
PAdES baseline profiles (ETSI EN 319 142)
.pades(PadesLevel::…) produces a PAdES baseline signature. The levels are cumulative — each builds
on the one below, and selecting a level auto-enables the lower-level requirements (a timestamp
for B-T and up, LTV for B-LT and up), so you don't have to wire timestamp / ltv separately.
| Level | Adds over the previous |
|---|---|
B_B | CAdES signed attributes + signing-certificate-v2 (the baseline) |
B_T | a signature timestamp (auto-uses the default TSA if none is set) |
B_LT | a DSS with the chain + CRLs + OCSP responses + a /VRI keyed to the signature |
B_LTA | a trailing document timestamp (/DocTimeStamp), the archive stamp |
let cfg = SignConfig::builder()
.place("F", [350, 60, 560, 160])?
.pades(PadesLevel::B_LTA) // signing-cert-v2 + TSA + DSS(OCSP+CRL+VRI) + document timestamp
.build();
let signed = sign_pdf(&pdf, &signer, &cfg)?;PAdES works together with certification: .certify(…).pades(PadesLevel::B_LTA) keeps the DocMDP
signature valid under the archive stamp.
LTV — the Document Security Store (DSS)
Long-term validation lets a viewer confirm a signature after the signing certificate expires or goes offline, by embedding the material needed to validate it inside the document. Mudrit writes this into the PDF's DSS:
- the signer's certificate chain,
- CRL responses, and
- OCSP responses (both fetched over plain HTTP, or injected via
ValidationMaterial), - plus a
/VRI(Validation-Related Information) entry keyed to the signature.
Enable it with .ltv(true) (embed the DSS so viewers show "LTV enabled") or implicitly via PAdES
B-LT / B-LTA. LTV is fetched live by default, but you can inject pre-fetched material and go
offline.
Fail-loud LTV
LtvPolicy::Require errors with Error::LtvIncomplete when no CRL/OCSP can be obtained, rather than
writing a silently half-LTV document. The default for ltv: true is BestEffort, which never lies —
sign_pdf_reported returns an LtvReport of exactly what was embedded. See
LTV.
RFC-3161 signature timestamps
A signature timestamp proves the signature existed at a certain time, from a trusted timestamp
authority (TSA). Attach one with .timestamp(Timestamp::url(url)) — this is what PAdES B-T and up
require, and Mudrit auto-uses the default TSA if a level needs one and none is set.
The built-in TSA speaks http and https with optional Basic / Bearer / header auth, over
pure-Rust TLS (rustls) — no OpenSSL, no system libraries. For anything it doesn't cover (mutual-TLS,
a proxy, a non-standard flow), implement the Timestamper trait and pass Timestamp::custom(…). See
Timestamps.
Document timestamp (/DocTimeStamp) — the archive stamp
A document timestamp is a standalone timestamp revision with SubFilter ETSI.RFC3161 — the
archive stamp that PAdES B-LTA adds, distinct from the per-signature timestamp above. It timestamps
the whole document as of that revision.
use mudrit_pdfsign::{add_document_timestamp, UrlTimestamper};
let stamped = add_document_timestamp(&signed, &UrlTimestamper::new("http://timestamp.comodoca.com"))?;add_document_timestamp is re-appliable: run it again over a previous archive to renew
long-term validity before the prior timestamp's certificate expires. See
Document timestamps.