How-to guides/Digital Signatures

Verify a PDF digital signature in Rust

Check that a PDF signature is cryptographically valid and that the document has not been modified since it was signed.

rust
use pdfluent::PdfDocument;

fn main() -> pdfluent::Result<()> {
    let doc = PdfDocument::open("signed.pdf")?;
    let report = doc.verify_signatures()?;
    println!("signed: {}, all valid: {}", report.is_signed(), report.all_valid());
    Ok(())
}

Step by step

1

Add PDFluent to your project

Add the pdfluent crate to Cargo.toml.

rust
[dependencies]
pdfluent = "1.0.0-beta.8"
2

Open the signed PDF

Load the document. A read-only borrow is sufficient for verification.

rust
use pdfluent::PdfDocument;

let doc = PdfDocument::open("signed_invoice.pdf")?;
3

List signatures in the document

Call doc.signatures() to get all signature fields. Each item includes the field name, signing time, and the raw certificate chain.

rust
let signatures = doc.signatures()?;
println!("Found {} signature(s)", signatures.len());

for sig in &signatures {
    println!("Field: {}", sig.field_name);
    println!("Signer: {}", sig.signer_name);
    println!("Timestamp: {:?}", sig.timestamp);
}
4

Verify signature integrity

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.

rust
let report = doc.verify_signatures()?;

if report.all_valid() {
    println!("OK - all signatures valid, document not modified");
} else {
    println!("FAIL - a signature is invalid or the document was modified");
}
5

Verify the certificate chain

Check that the signing certificate chains to a trusted root. Supply your own trust store or use the system store.

rust
let report = doc.verify_signatures()?;
println!("Signed: {}", report.is_signed());

for v in report.validations() {
    println!("Field {}: {:?}", v.info.field_name, v.status);
}

Notes and tips

  • integrity_valid checks cryptographic hash only. certificate_trusted checks the CA chain separately.
  • PDF signatures cover a specific byte range. Content added after signing (incremental updates) falls outside that range.
  • For LTV-enabled signatures, call result.ltv_valid() to check embedded OCSP and CRL data.
  • A self-signed certificate will produce certificate_trusted = false unless you add it to a custom TrustStore.

Why PDFluent for this

Pure Rust

No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.

Memory safe

Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.

Runs anywhere

Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.

Frequently asked questions