Mudrit
Cookbook

Signature Shapes

Single, multi-shared, and multi-chained signatures, certification (DocMDP), multi-party re-signing, and explicit field-lock

How many signature fields a document gets, whether the first signature certifies the document, and how a second party can safely add another signature on top — this page covers the shape of the signature layer itself, independent of what's inside each signature. Every recipe is a self-contained snippet for your own project; see Cookbook for how they're written.

Recipes

RecipeWhat it showsFeature
multi_signatureSingle vs MultiShared vs MultiChainedpfx
certify_and_lockDocMDP: approval vs Locked / FormsAndSignatures / …Annotationspfx
certified_variantsCertified Single (1 panel entry) / MultiShared (N entries) / + encryptedpfx
certify_then_approveCertify (P3) then a second party appends an approval signature; both validpfx
resign_multipartyAuto-append: signer A then B; plain and password-protectedpfx
field_lockExplicit FieldMDP /Action All field-lock via add_locked_signaturepfx

Single vs MultiShared vs MultiChained

MethodResult
SingleONE signature; a clickable widget on every resolved page (one revision).
MultiSharedN fields sharing ONE signature value (one revision; Adobe shows N fields).
MultiChainedN independent signatures, each its own revision (e.g. multi-party).
use mudrit::prelude::*;

let signer = PfxSigner::from_file("signer.pfx", "password")?;

let cfg = SignConfig::builder()
    .method(Method::MultiChained)
    .place("F", [350, 60, 560, 160])?
    .place("5", [350, 60, 560, 160])?
    .place("L", [350, 60, 560, 160])?
    .timestamp(Timestamp::url(mudrit::DEFAULT_TSA_URL))
    .ltv(true)
    .build();

let signed = sign_pdf(&pdf, &signer, &cfg)?;

Repo example: multi_signature — ships with the licensed source bundle.

Certification levels (DocMDP)

An approval signature (the default) just signs. A certifying signature — which must be the first signature — sets the document's DocMDP permission level:

ConfigDocMDP PMeaning
.approval() (default)ordinary signature; more allowed
.certify(Certify::Locked)1no changes allowed after
.certify(Certify::FormsAndSignatures)2form-fill + signing allowed
.certify(Certify::FormsSignaturesAndAnnotations)3+ annotations allowed
use mudrit::prelude::*;

let cfg = SignConfig::builder()
    .place("F", [350, 60, 560, 160])?
    .certify(Certify::Locked)
    .timestamp(Timestamp::url(mudrit::DEFAULT_TSA_URL))
    .ltv(true)
    .build();

let signed = sign_pdf(&pdf, &signer, &cfg)?;

Repo examples: certify_and_lock, certified_variants (source bundle). See the Certifying guide.

Certify, then a second party approves

A P2/P3 certification permits later signatures — a P1 Locked certification would forbid them and any later signature would invalidate it. sign_pdf detects the already-signed input and auto-appends the approval as a new revision, so both signatures stay valid.

use mudrit::prelude::*;

// 1) authority certifies at P3 — a later VISIBLE signature adds a widget annotation, which
//    needs P3 (FormsSignaturesAndAnnotations); an invisible later signature could use P2.
let certify_cfg = SignConfig::builder()
    .place("F", [350, 60, 560, 160])?
    .certify(Certify::FormsSignaturesAndAnnotations)
    .ltv(true)
    .timestamp(Timestamp::url(mudrit::DEFAULT_TSA_URL))
    .build();
let certified = sign_pdf(&pdf, &signer, &certify_cfg)?;

// 2) a second party appends an ordinary approval — auto-detected as a new revision
let approve_cfg = SignConfig::builder().place("F", [40, 60, 250, 160])?.approval().build();
let signed      = sign_pdf(&certified, &second_signer, &approve_cfg)?;

If the prior signature was password-protected, pass the same password via PdfReader::from(bytes).password("…") and the appended revision is encrypted with the document's own key.

Repo examples: certify_then_approve, resign_multiparty (source bundle).

Explicit field-lock

add_locked_signature is the lower-level alternative: it appends a signature carrying an explicit FieldMDP /Action All reference (no document-level DocMDP change) — use it to lock form fields without certifying the whole document. Pass a TSA URL for a timestamp, or None for none.

use mudrit::prelude::*;

let locked = add_locked_signature(
    &already_signed_pdf,
    1,                                     // page
    [350, 60, 560, 160],                   // rect
    "DirectorSignature",                   // field name
    &signer,
    Some("http://timestamp.comodoca.com"), // TSA URL, or None
)?;

Repo example: field_lock (source bundle). See add_locked_signature.

Certification order and re-signing

.certify(...) must be the first signature — certifying an already-signed document is rejected. Multi-party flows rely on sign_pdf's auto-append: passing an already-signed PDF back into sign_pdf appends a new revision instead of rebuilding the document, so earlier signatures stay valid. If the prior signature was password-protected, pass the same password via PdfReader(...).password(...) and the appended revision is encrypted with the document's own key.

Test cert; network for timestamp/LTV

The source-bundle programs use the bundled samples/ABC12.pfx test certificate — supply your own DSC in your project. Recipes that add .timestamp(...) or .ltv(true) need outbound network for the TSA / CRL / OCSP fetch.

Next

On this page