Check that a PDF signature is cryptographically valid and that the document has not been modified since it was signed.
use pdfluent::{PdfDocument, SignatureVerifier};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = PdfDocument::open("contract_signed.pdf")?;
let verifier = SignatureVerifier::new();
for sig in doc.signatures() {
let result = verifier.verify(&sig)?;
println!("Signature: {}", sig.field_name());
println!(" Integrity: {}", result.integrity_valid);
println!(" Certificate trusted: {}", result.certificate_trusted);
println!(" Signer: {:?}", result.signer_name);
}
Ok(())
}Add the pdfluent crate to Cargo.toml.
[dependencies]
pdfluent = "0.9"Load the document. A read-only borrow is sufficient for verification.
use pdfluent::PdfDocument;
let doc = PdfDocument::open("signed_invoice.pdf")?;Call doc.signatures() to get all signature fields. Each item includes the field name, signing time, and the raw certificate chain.
let signatures = doc.signatures();
println!("Found {} signature(s)", signatures.len());
for sig in &signatures {
println!("Field: {}", sig.field_name());
println!("Signing time: {:?}", sig.signing_time());
println!("Certificate subject: {}", sig.certificate().subject());
}SignatureVerifier checks that the signed byte range matches the current file contents. If any byte outside the signature field has changed, integrity_valid is false.
use pdfluent::SignatureVerifier;
let verifier = SignatureVerifier::new();
for sig in doc.signatures() {
let result = verifier.verify(&sig)?;
if result.integrity_valid {
println!("OK - document not modified since signing");
} else {
println!("FAIL - document was modified after signing");
}
}Check that the signing certificate chains to a trusted root. Supply your own trust store or use the system store.
use pdfluent::{SignatureVerifier, TrustStore};
// Use system root certificates
let verifier = SignatureVerifier::with_trust_store(TrustStore::system());
for sig in doc.signatures() {
let result = verifier.verify(&sig)?;
println!("Trusted: {}", result.certificate_trusted);
println!("Signer: {:?}", result.signer_name);
println!("Valid from: {:?}", result.certificate_valid_from);
println!("Valid until: {:?}", result.certificate_valid_until);
}No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.
Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.
Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.