Mudrit
Reference

Deferred Signing

prepare_signature, PreparedSignature, and SigningCertificate — split PDF preparation from an external hash-then-sign key operation

Part of mudrit-pdfsign

Deferred (two-step, "hash-then-sign") signing splits sign_pdf into a prepare step (builds the PDF, no private key) and a finalize step (embeds an externally-produced signature). See the Deferred Signing guide for the full walkthrough and the v1 scope table.

prepare_signature

pub fn prepare_signature(
    input: impl Into<PdfReader>,
    identity: &SigningCertificate,
    cfg: &SignConfig,
) -> Result<PreparedSignature>

Builds the PDF — placeholders, the AcroForm field, and any DocMDP / DSS — and returns a PreparedSignature exposing the bytes to sign. No private key is used here. cfg is the same SignConfig as in-process signing, minus the key; out-of-scope configurations (encrypted input/output, Method::MultiChained, PAdES B-LT/B-LTA, already-signed input) return Error::InvalidInput.

use mudrit_pdfsign::{prepare_signature, SigningCertificate, SignConfig};
# fn my_remote_signer(_: &[u8]) -> mudrit_pdfsign::Result<Vec<u8>> { unimplemented!() }
# let pdf: Vec<u8> = Vec::new();
# let leaf_cert_der: Vec<u8> = Vec::new();
# let chain_ders: Vec<Vec<u8>> = Vec::new();

// STEP 1 (server): cert + chain are known up front; the key is remote.
let identity = SigningCertificate::new(leaf_cert_der).chain(chain_ders);
let prepared = prepare_signature(&pdf, &identity, &SignConfig::builder().build())?;
let to_sign = prepared.signed_attributes().to_vec();   // or prepared.digest()

// STEP 2 (cloud HSM / browser / mobile): produce the signature out-of-process.
let signature = my_remote_signer(&to_sign)?;            // RSA PKCS#1 / PSS, or ECDSA DER {r,s}

// STEP 3 (server): embed it.
let signed_pdf = prepared.finalize(&signature)?;
# Ok::<(), mudrit_pdfsign::Error>(())

SigningCertificate

Everything prepare_signature needs except the private key: the leaf certificate, its chain, and the scheme the remote key signs with. Clone + Debug.

Prop

Type

Constructors and methods

Prop

Type

The algorithm must match the remote key

algorithm selects the digest and how the SignedData is labelled. If the remote key produces ECDSA P-256 but the identity says RSA, the finalized signature is mislabelled and rejected by validators.

PreparedSignature

A PDF prepared for signing, awaiting an externally-produced signature. Returned by prepare_signature; Clone, with a Debug that hides the PDF bytes and signed attributes.

Prop

Type

What the external signer must do

Apply the same operation a local Signer would to signed_attributes(): hash with algorithm()'s digest and produce the signature — a raw RSA PKCS#1 v1.5 / PSS signature, or an ECDSA SEQUENCE { r, s } DER. If the API signs a pre-computed hash instead, feed it digest() — that is exactly algorithm.digest(signed_attributes()).

// request A — prepare, then stash the blob (DB / cache / queue)
let blob = prepared.to_bytes()?;

// request B — restore, embed the externally-produced signature
let prepared = PreparedSignature::from_bytes(&blob)?;
let signed = prepared.finalize(&signature)?;

Timestamps are not serializable

to_bytes errors if a timestamp was configured. For a timestamped (B-T) deferred flow, either finalize in the same process, or prepare_signature with Timestamp::None and pass the TSA to finalize_with_timestamp after from_bytes.

v1 scope

Fresh (unsigned), unencrypted input; Method::Single / Method::MultiShared; optional certification, LTV, and PAdES B-B / B-T. Encrypted output, Method::MultiChained, appending to an already-signed PDF, and PAdES B-LT / B-LTA are rejected with Error::InvalidInput — use the in-process sign_pdf for those.

Next

On this page