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
| Crate | Recipe | Shows |
|---|---|---|
mudrit-keystore | keystore_discovery | KeyStore: list aliases → signer(alias) → raw .sign() (no PDF) |
mudrit-keystore | custom_engine | A Signer driving your own pipeline (raw signature + chain) |
mudrit-keystore | pkcs11_picker | Pkcs11Picker standalone (select → Signer, no PDF) — pkcs11-picker |
mudrit-pdfsign | standalone_pfx | The engine + a backend, no facade |
mudrit-pdfsign | standalone_custom_signer | Engine with no backend — builds with --no-default-features |
# 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 bytesRepo 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 builderRepo example:
custom_engine(source bundle). The cross-platform IcedPkcs11Pickeralso lives inmudrit-keystore(featurepkcs11-picker) and returns aBox<dyn Signer>with no PDF dependency — repo examplepkcs11_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
Advanced (Network / Hardware)
PAdES levels, PDF/A, custom timestamp authorities, Windows-store and PKCS#11 token signing, and SoftHSM2-backed ECDSA diagnostics
Reference
API reference for the Mudrit PDF-signing SDK — entry points, SignConfig, placement, appearance, timestamps, and PAdES, field by field