How-to guides/Security & Encryption

Open a password-protected PDF in Rust

Pass a user or owner password through OpenOptions to decrypt a PDF at load time, then work with it like any other document.

rust
use pdfluent::prelude::*;

fn main() -> Result<()> {
    let doc = PdfDocument::open_with(
        "confidential.pdf",
        OpenOptions::new().with_password("hunter2"),
    )?;

    println!("Opened {} pages", doc.page_count());
    Ok(())
}
Install:cargo add pdfluent@1.0.0-beta.5Download SDK →

Step by step

1

Provide the password via OpenOptions

PdfDocument::open_with takes a path and an OpenOptions. Chain .with_password(...) to pre-provision the user or owner password. Owner passwords grant full access regardless of permissions.

rust
use pdfluent::prelude::*;

let opts = OpenOptions::new().with_password("hunter2");
let doc = PdfDocument::open_with("confidential.pdf", opts)?;
2

Handle a wrong password cleanly

A wrong password returns Error::DecryptionFailed with reason WrongPassword. Match on the stable error code to prompt the user or fall back to a password-recovery flow.

rust
use pdfluent::prelude::*;

match PdfDocument::open_with(
    "confidential.pdf",
    OpenOptions::new().with_password("maybe_wrong"),
) {
    Ok(doc) => println!("opened with {} pages", doc.page_count()),
    Err(e) if e.code() == "E-SECURITY-DECRYPTION-FAILED" => {
        eprintln!("wrong password — try again");
    }
    Err(e) => return Err(e),
}
3

Read the password from a secret store

Don't hard-code secrets. Read the password from your runtime's secret manager — environment variable, vault, or a config file loaded through your existing secret-management layer.

rust
use pdfluent::prelude::*;

let pw = std::env::var("PDF_OPEN_PASSWORD")
    .expect("PDF_OPEN_PASSWORD env var not set");

let doc = PdfDocument::open_with(
    "confidential.pdf",
    OpenOptions::new().with_password(pw),
)?;
4

Open from bytes with a password

If the PDF is already in memory (blob from a database, response from an API), use from_bytes_with with the same OpenOptions. No filesystem roundtrip required.

rust
use pdfluent::prelude::*;

let bytes: Vec<u8> = fetch_from_backend()?;
let doc = PdfDocument::from_bytes_with(
    &bytes,
    OpenOptions::new().with_password("hunter2"),
)?;

Notes and tips

  • The user password lets you view the document; the owner password additionally unlocks all permissions. PDFluent accepts either — the correct password opens the file.
  • A wrong password returns Error::DecryptionFailed { reason: DecryptionFailureReason::WrongPassword }. Match on .code() == "E-SECURITY-DECRYPTION-FAILED" for a stable check.
  • After opening, the document is fully decrypted in memory. Subsequent operations (text extraction, form fills, save) work normally. The saved output is unencrypted unless you re-encrypt with doc.encrypt(...).
  • PDFluent supports RC4-128, AES-128, and AES-256 encrypted files. Some older or very permissive documents have no password at all — opening them without OpenOptions works as usual.

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