Encrypt, decrypt, and set PDF permissions

This guide shows you how to manage PDF passwords and access controls using the PDFluent SDK. It is for Rust developers who need to secure or modify existing PDF documents.

Add PDFluent to Cargo.toml

Encryption removal is part of the encryption feature.
toml
# Cargo.toml
[dependencies]
pdfluent = "1.3.0"

Encrypt a PDF with a password in Rust

Protect a PDF with a user password and an owner password. Choose AES-256 and configure fine-grained permission flags.
rust
use pdfluent::{PdfDocument, EncryptOptions};

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::open("report.pdf")?;
    let opts = EncryptOptions::aes256()
        .with_user_password("open-sesame")
        .with_owner_password("owner-secret");
    doc.encrypt(opts)?;
    doc.save("report-encrypted.pdf")?;
    Ok(())
}

Complete program, compiled against the published crate: Code on GitHub →

The same code, typed and run on screen. Watch on YouTube

  1. Step 1

    Open the PDF

    Open the document you want to protect. Use a mutable binding.

    rust
    use pdfluent::prelude::*;
    
    let mut doc = PdfDocument::open("report.pdf")?;
  2. Step 2

    Choose the encryption algorithm

    EncryptOptions::aes256() uses AES-256, which is the current best practice. EncryptOptions::aes128() is accepted but the 1.0 backend currently always emits AES-256 state; if strict 128-bit output matters for interop, track this as a known deviation.

    rust
    let opts = EncryptOptions::aes256();
  3. Step 3

    Set user and owner passwords

    The user password is required to open the document. The owner password unlocks all permissions. If you omit with_user_password, the document opens without a password but still enforces permission flags.

    rust
    let opts = opts
        .with_user_password("open_document_2025")
        .with_owner_password("full_access_secret");
  4. Step 4

    Configure permissions

    Start from a preset (Permissions::full_access, print_only, read_only, or annotate) and opt out of individual rights with the with_*(false) builders: with_print, with_modify, with_copy, with_annotate, with_fill_forms, with_extract_accessibility, with_assemble, with_print_high_quality.

    rust
    let perms = Permissions::full_access()
        .with_modify(false)
        .with_copy(false);
    
    let opts = opts.with_permissions(perms);
  5. Step 5

    Encrypt and save

    Call encrypt() then save() to write the protected file. encrypt takes EncryptOptions by value (no reference).

    rust
    doc.encrypt(opts)?;
    doc.save("report_protected.pdf")?;
  • AES-256 requires PDF 1.7 or later. If you need compatibility with older readers, use EncryptOptions::aes128() — note that the 1.0 SDK currently emits AES-256 state regardless of the algorithm tag; strict AES-128 is tracked as a 1.1 follow-up.
  • The owner password controls the permission flags. Without it, even the software that created the PDF cannot bypass the restrictions.
  • Encryption does not compress the document. The file size stays roughly the same.
  • PDF/A documents must not be encrypted. Remove encryption before validating for PDF/A compliance.
What is the difference between the user password and the owner password?
The user password is needed to open and view the document. The owner password is needed to change permissions, remove encryption, or perform restricted actions. They can be the same string, but using different values is more secure.
Can I encrypt only part of a PDF?
No. PDF encryption applies to the entire document. If you need per-section access control, split the document first and encrypt each part separately.
Does encryption prevent printing?
Only if you set with_print(false) on your Permissions. Encryption and printing permission are independent settings.
Can PDFluent decrypt a PDF I did not encrypt myself?
Yes, if you have the password. Use OpenOptions::new().with_password("...") and pass it to PdfDocument::open_with. If the password is wrong, the call returns Err(Error::DecryptionFailed { reason: DecryptionFailureReason::WrongPassword }).

Decrypt a password-protected PDF in Rust

Open an encrypted PDF with the user or owner password and save an unprotected copy. Works with RC4-128 and AES-128/256 encrypted files.
rust
use pdfluent::{PdfDocument, OpenOptions};

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::open_with(
        "locked.pdf",
        OpenOptions::new().with_password("s3cret"),
    )?;
    doc.decrypt("s3cret")?;
    doc.save("decrypted.pdf")?;
    Ok(())
}
  1. Step 1

    Open the encrypted PDF

    Use PdfDocument::open_with() and provide the user or owner password. The method returns an error if the password is wrong.

    rust
    use pdfluent::{PdfDocument, OpenOptions};
    
    let mut doc = PdfDocument::open_with("protected.pdf", OpenOptions::new().with_password("open123"))?;
  2. Step 2

    Handle a wrong password

    Match on Error::WrongPassword to give the user a clear error instead of a generic failure.

    rust
    use pdfluent::{PdfDocument, OpenOptions};
    
    let result = PdfDocument::open_with("protected.pdf", OpenOptions::new().with_password("guess"));
    match result {
        Ok(doc) => { /* proceed */ }
        Err(_) => eprintln!("Could not open - wrong or missing password."),
    }
  3. Step 3

    Check the encryption details

    After opening, inspect the encryption type and permission flags that were set by the document author.

    rust
    // Strip the encryption so the saved copy opens without a password
    doc.decrypt("open123")?;
  4. Step 4

    Remove encryption

    Call decrypt(password) to strip all password protection and permission flags from the document in memory.

    rust
    doc.save("decrypted.pdf")?;
  5. Step 5

    Save the unprotected document

    Save to a new path. The saved file will open in any PDF reader without a password.

    rust
    // Verify by re-opening without a password
    let check = PdfDocument::open("decrypted.pdf")?;
    println!("Re-opened without a password: {} pages", check.page_count());
  • You can use the owner password to open the document even when the user password is different. The owner password grants full access regardless of permission flags.
  • After calling open_with(), all normal PDFluent operations work on the document. You do not need to remove encryption to extract text or render pages.
  • Some PDFs are encrypted but have no user password. They open without a password in readers but still have permission flags. open_with() with an empty string handles this case.
Can I decrypt a PDF without the password?
No. PDFluent requires the correct password to open an encrypted document. Brute-force or dictionary attacks are outside the scope of the library.
What encryption algorithms does PDFluent support?
RC4-40, RC4-128, AES-128, and AES-256. These cover all standard PDF encryption formats from PDF 1.1 through PDF 2.0.
Can I open an encrypted PDF just to extract text, without removing encryption?
Yes. Call open_with() with the password and then call text() or any other read operation directly. You only need decrypt(password) if you want to save an unprotected copy.
Does removing encryption change anything else in the document?
No. decrypt(password) only removes the encryption dictionary and clears the permission flags. Page content, fonts, metadata, and annotations are untouched.

Add a user or owner password to a PDF in Rust

Protect a PDF with a password so readers must enter it to open the file, or set an owner password to restrict editing.
rust
use pdfluent::{PdfDocument, EncryptOptions};

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::open("invoice.pdf")?;
    doc.encrypt(EncryptOptions::aes256().with_user_password("s3cret"))?;
    doc.save("invoice-protected.pdf")?;
    Ok(())
}
  1. Step 1

    Add PDFluent with encryption support

    The encryption feature includes AES-128 and AES-256 support.

    rust
    # Cargo.toml
    [dependencies]
    pdfluent = "1.3.0"
  2. Step 2

    Open the source document

    Open the PDF you want to protect. If it is already encrypted, open it with the current owner password first.

    rust
    use pdfluent::PdfDocument;
    
    let mut doc = PdfDocument::open("report.pdf")?;
  3. Step 3

    Configure AES-256 encryption

    The first argument to aes256() is the owner password. The second is the user password. Set the user password to an empty string to allow opening without a password while still restricting permissions.

    rust
    use pdfluent::EncryptOptions;
    
    // Both passwords set - readers must enter user-pw to open
    let opts = EncryptOptions::aes256().with_owner_password("owner-pw-123").with_user_password("user-pw-456");
    
    // Owner password only - file opens without a password, but editing is restricted
    let opts = EncryptOptions::aes256().with_owner_password("owner-pw-123").with_user_password("");
  4. Step 4

    Apply the encryption and save

    doc.encrypt() modifies the in-memory document. The protection is written to disk on save.

    rust
    doc.encrypt(opts)?;
    doc.save("report-protected.pdf")?;
    println!("Saved report-protected.pdf");
  5. Step 5

    Verify the password is set

    Re-open the saved file and confirm it requires a password.

    rust
    let result = PdfDocument::open("report-protected.pdf");
    match result {
        Err(_) => println!("Correct: file requires a password to open."),
        Ok(_) => println!("Warning: file opened without a password."),
    }
  • AES-256 is supported by all PDF readers released after 2010. For maximum compatibility with very old readers, use EncryptOptions::aes128 instead.
  • An empty user password means the PDF opens without a password prompt but is still encrypted. Permission flags are enforced by compliant readers.
  • Store the owner password securely. Without it, you cannot change or remove the encryption later. PDFluent cannot crack or bypass PDF encryption.
  • Password strength matters. A PDF with a short or common user password provides minimal protection against brute-force attacks.
What is the difference between a user password and an owner password?
The user password (also called the open password) must be entered to open the PDF. The owner password is used to change encryption settings and permissions. Setting only an owner password leaves the PDF openable by anyone, but editing is restricted.
Does setting a password also set permissions?
Not by default. doc.encrypt() with just an EncryptOptions encrypts the file but leaves all permission flags open. To restrict specific operations, combine with a Permissions builder. See the Set PDF Permissions guide.
Can I change the password without removing and re-adding encryption?
Yes. Open the file with the owner password, then call doc.encrypt() with the new EncryptOptions and save. This replaces the existing encryption in one step.
How do I remove the password from a PDF?
Open the PDF with the owner password and call doc.decrypt(password). Then save the file. See the Remove PDF Password guide for the full example.

Remove the password from a PDF you own in Rust

Decrypt a password-protected PDF and save a clean, unencrypted copy. Requires the owner password.
rust
use pdfluent::{PdfDocument, OpenOptions};

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::open_with(
        "locked.pdf",
        OpenOptions::new().with_password("s3cret"),
    )?;
    doc.decrypt("s3cret")?;
    doc.save("unlocked.pdf")?;
    Ok(())
}
  1. Step 1

    Open the PDF with the owner password

    You need the owner password to remove encryption. The user password only grants read access. If you only have the user password, you cannot remove or modify the encryption.

    rust
    use pdfluent::{PdfDocument, OpenOptions};
    
    let mut doc = PdfDocument::open_with(
        "protected.pdf",
        OpenOptions::new().with_password("owner-pw-123"),
    )?;
  2. Step 2

    Handle the wrong password case

    open_with() returns Error::WrongPassword if the password is incorrect. Handle this in a pipeline to log failures without crashing.

    rust
    use pdfluent::{PdfDocument, OpenOptions};
    
    match PdfDocument::open_with("protected.pdf", OpenOptions::new().with_password("owner-pw-123")) {
        Ok(doc) => println!("Opened successfully"),
        Err(_) => eprintln!("Wrong or missing password."),
    }
  3. Step 3

    Remove encryption and save

    decrypt(password) strips all encryption dictionaries from the document. The saved file is a plain PDF with no password required.

    rust
    doc.decrypt("owner-pw-123")?;
    doc.save("unprotected.pdf")?;
    
    // Verify by opening without a password
    let _check = PdfDocument::open("unprotected.pdf")?;
    println!("Saved an unprotected copy.");
  4. Step 4

    Batch remove passwords from multiple PDFs

    Combine with a directory scan to decrypt a folder of PDFs at once.

    rust
    use std::fs;
    use pdfluent::{PdfDocument, OpenOptions};
    
    let password = "owner-pw-123";
    
    for entry in fs::read_dir("./encrypted")?.filter_map(|e| e.ok()) {
        let path = entry.path();
        if path.extension().map_or(false, |e| e == "pdf") {
            match PdfDocument::open_with(&path, OpenOptions::new().with_password(password)) {
                Ok(mut doc) => {
                    doc.decrypt(password)?;
                    let out = std::path::Path::new("./decrypted").join(path.file_name().unwrap());
                    doc.save(out)?;
                    println!("Decrypted: {}", path.display());
                }
                Err(_) => eprintln!("Could not open: {}", path.display()),
            }
        }
    }
  • You must have the owner password to remove encryption. PDFluent does not brute-force or crack passwords.
  • If a PDF only has an owner password (empty user password), the file opens without a password but is still encrypted. You still need the owner password to call decrypt(password).
  • Saving to the same file path as the input overwrites the original. Keep a backup of the original before running this operation.
Can I remove encryption with only the user password?
No. The user password grants read access but not the ability to change encryption or permissions. You need the owner password to call decrypt(password).
What if the PDF has both a user password and an owner password?
Supply the owner password to open_with(). The owner password always grants full access. After opening with the owner password, call decrypt(password) as normal.
How do I remove only the user password while keeping permission restrictions?
Open with the owner password, call doc.encrypt() with a new EncryptOptions that has an empty user password string and the desired permissions, then save. This keeps encryption active but removes the open-password requirement.
Does PDFluent support RC4 decryption for older PDFs?
Yes. PDFluent can open and decrypt PDFs using RC4-40, RC4-128, AES-128, and AES-256. After decryption, the saved output uses no encryption regardless of the original algorithm.

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::{PdfDocument, OpenOptions};

fn main() -> pdfluent::Result<()> {
    let doc = PdfDocument::open_with(
        "locked.pdf",
        OpenOptions::new().with_password("s3cret"),
    )?;
    println!("{} pages", doc.page_count());
    Ok(())
}

Complete program, compiled against the published crate: Code on GitHub →

The same code, typed and run on screen. Watch on YouTube

  1. 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("s3cret");
    let doc = PdfDocument::open_with("locked.pdf", opts)?;
  2. Step 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(
        "locked.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. Step 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(
        "locked.pdf",
        OpenOptions::new().with_password(pw),
    )?;
  4. Step 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("s3cret"),
    )?;
  • 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.
How do I tell whether a PDF is encrypted before opening?
PDFluent doesn't expose a standalone is_encrypted() check on 1.0 — call PdfDocument::open(path) first; if the document is encrypted it returns Error::DecryptionFailed, at which point you know to retry with a password via open_with.
Can I save the decrypted file back to disk?
Yes. After open_with succeeds, doc.save("out.pdf")? writes the document as an unencrypted PDF. To keep it encrypted, call doc.encrypt(...) before saving.
What error code signals a wrong password?
Error::DecryptionFailed.code() returns "E-SECURITY-DECRYPTION-FAILED". The docs_url() resolves to https://pdfluent.com/errors/E-SECURITY-DECRYPTION-FAILED.
Can I try multiple passwords?
Loop over candidates, calling PdfDocument::open_with with each. Each call is independent; a failure doesn't mark the file as locked.

Check whether a PDF is protected in Rust

1.0 does not report a document's permission bits. It answers whether the file is protected and whether your password opens it -- and it sets permissions when you write one.
rust
use pdfluent::error::DecryptionFailureReason;
use pdfluent::{Error, OpenOptions, PdfDocument};

fn main() -> pdfluent::Result<()> {
    // 1.0 does not report the permission bits of a document it opened. What it
    // does answer is whether the file is protected at all, and whether the
    // password you have is the one it wants.
    match PdfDocument::open("document.pdf") {
        Ok(doc) => println!("no password needed: {} pages", doc.page_count()),
        Err(Error::DecryptionFailed { reason, .. }) => {
            // Without a password there is only one answer worth giving, and the
            // library gives that one: PasswordRequired. WrongPassword can only
            // come back from an open that carried a password.
            println!("protected ({reason:?}); trying the one we have");
            match PdfDocument::open_with(
                "document.pdf",
                OpenOptions::new().with_password("user-password"),
            ) {
                Ok(doc) => println!("opened: {} pages", doc.page_count()),
                Err(Error::DecryptionFailed { reason, .. }) => match reason {
                    DecryptionFailureReason::WrongPassword => println!("that is not the password"),
                    other => println!("cannot open it: {other:?}"),
                },
                Err(e) => return Err(e),
            }
        }
        Err(e) => return Err(e),
    }

    Ok(())
}
  1. Step 1

    Find out whether the document is protected

    An encrypted document opened without a password fails with Error::DecryptionFailed and the reason PasswordRequired. That is deliberate: an open that offered no password has no typo to report, so the library does not say WrongPassword to someone who never gave one.

    rust
    use pdfluent::error::DecryptionFailureReason;
    use pdfluent::{Error, PdfDocument};
    
    match PdfDocument::open("document.pdf") {
        Ok(doc) => println!("open: {} pages", doc.page_count()),
        Err(Error::DecryptionFailed { reason, .. }) => match reason {
            DecryptionFailureReason::PasswordRequired => println!("a password is required"),
            other => println!("cannot decrypt: {other:?}"),
        },
        Err(e) => return Err(e),
    }
  2. Step 2

    Try the password you have, and read the answer

    Supply it through OpenOptions. This is the only shape in which WrongPassword can come back, so it is where a wrong candidate is told apart from a file that simply needs one. The user password is enough to read the document; the owner password is what you need to change how it is protected.

    rust
    use pdfluent::error::DecryptionFailureReason;
    use pdfluent::{Error, OpenOptions, PdfDocument};
    
    match PdfDocument::open_with(
        "protected.pdf",
        OpenOptions::new().with_password("user-password"),
    ) {
        Ok(doc) => println!("{} pages", doc.page_count()),
        Err(Error::DecryptionFailed { reason, .. }) => match reason {
            DecryptionFailureReason::WrongPassword => println!("wrong password"),
            other => println!("cannot open it: {other:?}"),
        },
        Err(e) => return Err(e),
    }
  3. Step 3

    Set the permissions you want on the way out

    Permissions are something you write, not something you read back: build them and hand them to encrypt(). Permissions::print_only, read_only, annotate and full_access are the presets, with_print and friends the fine control.

    rust
    use pdfluent::{EncryptOptions, Permissions};
    
    let mut doc = PdfDocument::open("document.pdf")?;
    doc.encrypt(
        EncryptOptions::aes256()
            .with_user_password("user-password")
            .with_owner_password("owner-password")
            .with_permissions(Permissions::print_only()),
    )?;
    doc.save("restricted.pdf")?;
  • There is no doc.with_permissions() reader in 1.0, and no permission flags on an opened document. with_permissions is a builder method on EncryptOptions -- it sets what a document allows, and this page shows it in that position.
  • PasswordRequired and WrongPassword ask different things of a caller, so the library keeps them apart: an open that carried no password can only produce the first, whatever the engine underneath reported.
  • Permission bits are a request to the viewer, not enforcement. Any tool with the file can ignore them; encryption is what actually keeps a reader out.
  • Accessibility extraction stays enabled in every preset, per ISO 32000-2: a spec-compliant reader gives assistive technology access whatever the bits say.
  • Some producers set permission bits without encrypting the file at all. Those bits are unprotected metadata; nothing about them is binding.
How do I read the permission flags of a document?
You cannot in 1.0. The bits are parsed while decrypting but are not surfaced on PdfDocument, so this page shows the questions that can be answered: is it protected, and does this password open it.
Do I need the owner password?
Only to change how the document is protected. The user password -- or none, on an unprotected file -- is enough to open and read it.
How do I set permissions?
EncryptOptions::aes256() with a user and owner password, with_permissions to restrict, then doc.encrypt(). That is the third step above.

Set print, copy, and edit permissions on a PDF in Rust

Lock down what readers can do with your PDF. Restrict printing, copying text, editing, and form filling using the PDFluent SDK.
rust
use pdfluent::{PdfDocument, EncryptOptions, Permissions};

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::open("report.pdf")?;
    let opts = EncryptOptions::aes256()
        .with_owner_password("owner-secret")
        .with_permissions(Permissions::print_only());
    doc.encrypt(opts)?;
    doc.save("report-restricted.pdf")?;
    Ok(())
}
  1. Step 1

    Open the source document

    Open the PDF you want to restrict. If it is already encrypted you must supply the owner password.

    rust
    let mut doc = PdfDocument::open("input.pdf")?;
    // Or, if already encrypted:
    // let mut doc = PdfDocument::open_with("input.pdf", OpenOptions::new().with_password("current-owner-pw"))?;
  2. Step 2

    Define the permission set

    Use the Permissions builder to choose what is allowed. All operations default to denied when you use the builder.

    rust
    use pdfluent::Permissions;
    
    let permissions = Permissions::full_access()
        .with_print(false)       // block all printing
        .with_print_high_quality(false)
        .with_copy(false)        // block text/image copying
        .with_modify(false)      // block page editing
        .with_annotate(false)    // block adding comments
        .with_fill_forms(true);  // allow form data entry
  3. Step 3

    Apply AES-256 encryption with the permissions

    Pair the permission set with an encryption config. The owner password lets you change permissions later. The user password is what readers enter to open the file.

    rust
    use pdfluent::EncryptOptions;
    
    let opts = EncryptOptions::aes256().with_owner_password("owner-secret").with_user_password("user-secret")
        .with_permissions(permissions);
    
    doc.encrypt(opts)?;
  4. Step 4

    Save the output file

    Write the encrypted PDF to disk. The original file is not modified.

    rust
    doc.save("locked.pdf")?;
    println!("Saved locked.pdf");
  • AES-256 encryption requires PDF 1.7 or higher. PDFluent upgrades the PDF version automatically if needed.
  • The owner password must differ from the user password, otherwise most PDF readers ignore the permission flags.
  • Permissions without encryption have no effect. PDF readers only enforce flags when the file is encrypted.
  • To remove permissions later, open the file with the owner password and call doc.decrypt(password).
Does setting permissions prevent printing completely?
It prevents compliant PDF readers such as Adobe Acrobat, Preview, and Chrome from printing. Anyone with direct byte access to the file and an owner password can bypass this. Permissions are an access control hint, not DRM.
Can I allow low-resolution printing but block high-resolution printing?
Yes. Call .with_print(true).allow_high_res_printing(false) on the builder. PDF spec defines two separate permission bits for this.
What encryption algorithm does PDFluent use by default?
EncryptOptions::aes256 uses AES-256 in CBC mode as defined in PDF 1.7 extension level 3. AES-128 is also available via EncryptOptions::aes128 for compatibility with older readers.
How do I check which permissions are set on an existing PDF?
Open the document and call doc.with_permissions(). This returns a Permissions struct with bool fields for each flag. See the Check PDF Permissions guide for a full example.