Mudrit
Guides

Detached CMS

Sign arbitrary bytes with a detached CMS/PKCS#7 (.p7s) — no PDF, using any Signer backend

Part of mudrit-pdfsign

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 file

Detached 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().

OptionTypeDefaultEffect
timestampTimestampTimestamp::NoneAttach an RFC-3161 signature timestamp — the CAdES B-T shape (an unsigned attribute over the signature bytes)
signing_certificatebooltrueInclude the ESS signing-certificate-v2 signed attribute (RFC 5035) — the CAdES-BES proof binding the signature to the exact certificate
signing_timeboolfalseInclude 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 .p7s is 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.

Next

On this page