Detached CMS
Sign arbitrary bytes with a detached CMS/PKCS#7 (.p7s) — no PDF, using any Signer backend
Not every document is a PDF. sign_detached_cms produces a standalone detached CMS / PKCS#7
signature — a .p7s — over arbitrary bytes: XML, ZIP archives, firmware images, invoices, or any raw
buffer. It shares the same CMS core as the PDF engine, so the same key backends (PFX, PKCS#11 token,
Windows store, custom) and the same algorithms (RSA PKCS#1 / PSS, ECDSA) apply.
use mudrit_keystore::PfxSigner;
use mudrit_pdfsign::{sign_detached_cms, CmsOptions};
let signer = PfxSigner::from_file("samples/ABC12.pfx", "ABC12")?;
let data = std::fs::read("invoice.xml")?;
let p7s = sign_detached_cms(&signer, &data, &CmsOptions::default())?;
std::fs::write("invoice.xml.p7s", &p7s)?; // detached signature, next to the fileDetached means the content is not embedded
The .p7s carries the signature, not your data. A verifier recomputes the digest over the
original data and checks it against the CMS messageDigest attribute — so you distribute the
original file and its .p7s side by side. Keep them together; the signature is meaningless without
the exact bytes it was computed over.
Options — CmsOptions
Start from CmsOptions::default() (no timestamp, with the ESS signing-certificate attribute) and
chain the setters. CmsOptions is #[non_exhaustive]; construct it via default() / new().
| Option | Type | Default | Effect |
|---|---|---|---|
timestamp | Timestamp | Timestamp::None | Attach an RFC-3161 signature timestamp — the CAdES B-T shape (an unsigned attribute over the signature bytes) |
signing_certificate | bool | true | Include the ESS signing-certificate-v2 signed attribute (RFC 5035) — the CAdES-BES proof binding the signature to the exact certificate |
signing_time | bool | false | Include the PKCS#9 signingTime signed attribute (UTC) — enable it for legacy .p7s consumers that expect one inside the SignerInfo |
use mudrit_pdfsign::{CmsOptions, Timestamp};
let opts = CmsOptions::default()
.timestamp(Timestamp::url("http://timestamp.comodoca.com")) // RFC-3161 signature timestamp
.signing_certificate(true) // ESS signing-certificate-v2
.signing_time(true); // PKCS#9 signingTime (legacy)
let p7s = sign_detached_cms(&signer, &data, &opts)?;When to reach for it
- Non-PDF documents — sign an XML e-invoice, a firmware blob, or a release archive where a PDF signature has nowhere to live.
- Interoperable output — the
.p7sis standard detached CMS, so verifiers outside the PDF world (OpenSSL, Java, .NET) recompute and check it the same way. - The same identity everywhere — the key backend that signs your PDFs signs these bytes too, so a token or HSM identity produces both without extra plumbing.
The signer's algorithm() selects the digest and signature scheme, so a token that signs PDFs as
ECDSA P-256 produces an ECDSA .p7s here with no extra configuration.