Mudrit
Cookbook

Independently Usable Crates

mudrit-keystore and mudrit-pdfsign used entirely on their own — no facade, and in the engine's case, no bundled backend at all

Mudrit is split into a key-management layer (mudrit-keystore) and a PDF-signing engine (mudrit-pdfsign) joined by one trait, and the mudrit facade re-exports both. Every recipe elsewhere in this cookbook imports mudrit::prelude::* for convenience — but you don't have to take the whole bundle. Each crate is independently usable: depend on mudrit-keystore alone for pure key management (no PDF), or on mudrit-pdfsign alone for the engine with your own Signer (and, optionally, no bundled backend at all). The recipes below are self-contained snippets for exactly those leaner builds.

Recipes

CrateRecipeShows
mudrit-keystorekeystore_discoveryKeyStore: list aliases → signer(alias) → raw .sign() (no PDF)
mudrit-keystorecustom_engineA Signer driving your own pipeline (raw signature + chain)
mudrit-keystorepkcs11_pickerPkcs11Picker standalone (select → Signer, no PDF) — pkcs11-picker
mudrit-pdfsignstandalone_pfxThe engine + a backend, no facade
mudrit-pdfsignstandalone_custom_signerEngine with no backend — builds with --no-default-features
Cargo.toml — pick only the crate you need
# Pure key management, your own signing engine (no PDF):
mudrit-keystore = { version = "0.1", default-features = false, features = ["pfx"] }
# The PDF engine with your own Signer (no backend at all):
mudrit-pdfsign  = { version = "0.1", default-features = false }

mudrit-keystore alone — discovery + raw signing

mudrit-keystore gives you Java-KeyStore-style discovery and raw signing with no PDF engine in the dependency tree. The same aliases() / signer(alias) shape works for Pkcs11KeyStore and WinStoreKeyStore; PfxKeyStore is shown here.

use mudrit_keystore::{KeyStore, PfxKeyStore};

let store   = PfxKeyStore::from_file("signer.pfx", "password")?;
let entries = store.aliases()?;
for e in &entries {
    println!("alias={} CN={} serial={}", e.alias, e.cn, e.serial);
}

let signer  = store.signer(&entries[0].alias)?; // Box<dyn Signer> — no PDF involved
let raw_sig = signer.sign(b"hello, world")?;    // raw signature over any bytes

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

mudrit-keystore alone — drive your own protocol

Signer::sign returns a raw signature over arbitrary bytes plus the certificate chain — enough to build CMS, XML-DSig, or any custom protocol. PDF is not required; mudrit-pdfsign is just one consumer of the same trait.

use mudrit_keystore::{PfxSigner, Signer};

let signer  = PfxSigner::from_file("signer.pfx", "password")?;
let payload = b"arbitrary application data to sign";

let (cn, org)  = signer.subject();
let signature  = signer.sign(payload)?; // the private key never leaves the backend
// feed (payload, signature, signer.chain()) into your own CMS / protocol builder

Repo example: custom_engine (source bundle). The cross-platform Iced Pkcs11Picker also lives in mudrit-keystore (feature pkcs11-picker) and returns a Box<dyn Signer> with no PDF dependency — repo example pkcs11_picker.

mudrit-pdfsign alone — the engine with your own Signer

mudrit-pdfsign signs only through the Signer trait, so it compiles and runs with --no-default-features — no PFX / PKCS#11 / Windows code at all. Implement Signer against your HSM or cloud KMS and sign_pdf works unchanged; the whole pipeline (placement, PAdES, LTV, encryption) comes along.

use mudrit_pdfsign::mudrit_keystore::{Result as KsResult, SignatureAlgorithm, Signer};
use mudrit_pdfsign::{sign_pdf, SignConfig};

struct KmsSigner { leaf_der: Vec<u8>, chain_der: Vec<Vec<u8>> }

impl Signer for KmsSigner {
    fn certificate(&self) -> &[u8] { &self.leaf_der }
    fn chain(&self) -> &[Vec<u8>] { &self.chain_der }
    fn algorithm(&self) -> SignatureAlgorithm { SignatureAlgorithm::RsaPkcs1Sha256 }
    fn sign(&self, data: &[u8]) -> KsResult<Vec<u8>> {
        let _digest = self.algorithm().digest(data);
        todo!("wire this to your HSM / cloud KMS")
    }
}

let signer = KmsSigner { leaf_der, chain_der };
let cfg    = SignConfig::builder().place("F", [350, 60, 560, 160])?.build();
let signed = sign_pdf(&pdf, &signer, &cfg)?;

To use the engine with a bundled backend but without the facade, enable a feature (mudrit-pdfsign with features = ["pfx"]) and construct a PfxSigner directly — repo example standalone_pfx.

Repo example: standalone_custom_signer (source bundle) — builds with --no-default-features.

Why this matters

custom_signer on the Basics page shows the identical pattern through the mudrit facade. Seeing it work with --no-default-features on mudrit-pdfsign directly is the point: the Signer trait, not any bundled backend, is the real contract between key management and PDF signing — a lean build can skip every backend and still sign PDFs against your own key source.

Test cert vs. your DSC; the picker needs hardware

Where a bundled backend is used, the source-bundle programs run offline against the samples/ABC12.pfx test certificate — supply your own DSC in your project. The pkcs11_picker recipe is the one exception: it needs a real PKCS#11 module and a token to open the selection UI.

Next

On this page