Recursive AI

Encrypt a PDF with a password in C#

OnePDF is a free, open-source PDF library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

Require a password to open a PDF and record which operations a reader is permitted to perform.

Terminal
dotnet add package RecursiveAI.OnePdf

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

input.pdf is the three-page sample in the example zip.

C#
using OnePdf;
 
using var doc = PdfDocument.Open("input.pdf",
    new PdfOpenOptions { AllowEditing = true });
doc.Save("encrypted.pdf", new PdfSaveOptions
{
    Encryption = PdfEncryptionAction.Set,
    NewEncryption = new()
    {
        UserPassword = "reader-demo",
        OwnerPassword = "owner-demo",
        Cipher = PdfCipher.Aes256,
        Permissions = PdfPermissions.Print
    }
});
Console.WriteLine("Saved encrypted.pdf");
Text
Saved encrypted.pdf

Unzip the example, then dotnet run.

The full program

C#
using OnePdf;
 
using var doc = PdfDocument.Open("input.pdf",
    new PdfOpenOptions { AllowEditing = true });
doc.Save("encrypted.pdf", new PdfSaveOptions
{
    Encryption = PdfEncryptionAction.Set,
    NewEncryption = new()
    {
        UserPassword = "reader-demo",
        OwnerPassword = "owner-demo",
        Cipher = PdfCipher.Aes256,
        Permissions = PdfPermissions.Print
    }
});
Console.WriteLine("Saved encrypted.pdf");
try
{
    using var wrong = PdfDocument.Open("encrypted.pdf",
        new PdfOpenOptions { Password = "wrong" });
    throw new InvalidOperationException("Wrong password accepted.");
}
catch (PdfPasswordException)
{
    Console.WriteLine("Wrong password rejected");
}
foreach (var password in new[] { "reader-demo", "owner-demo" })
{
    using var opened = PdfDocument.Open("encrypted.pdf",
        new PdfOpenOptions { Password = password });
    Console.WriteLine($"{opened.Encryption!.AccessLevel}: {opened.Encryption.Cipher}");
    Console.WriteLine($"Permissions: {opened.Permissions}");
}

dotnet run prints:

Text
Saved encrypted.pdf
Wrong password rejected
User: Aes256
Permissions: Print
Owner: Aes256
Permissions: Print

A wrong password throws PdfPasswordException. OnePDF records permission flags and does not enforce them.

Variations

Combine permission flags with |. This records permission to print at high quality and copy content:

C#
using OnePdf;
 
using var doc = PdfDocument.Open("input.pdf",
    new PdfOpenOptions { AllowEditing = true });
doc.Save("print-and-copy.pdf", new PdfSaveOptions
{
    Encryption = PdfEncryptionAction.Set,
    NewEncryption = new()
    {
        UserPassword = "reader-demo",
        OwnerPassword = "owner-demo",
        Permissions = PdfPermissions.Print
            | PdfPermissions.PrintHighQuality
            | PdfPermissions.CopyContent
    }
});
using var saved = PdfDocument.Open("print-and-copy.pdf",
    new PdfOpenOptions { Password = "reader-demo" });
Console.WriteLine($"Permissions: {saved.Permissions}");
Text
Permissions: Print, CopyContent, PrintHighQuality

After running the full program, remove encryption using the owner password:

C#
using OnePdf;
 
using var doc = PdfDocument.Open("encrypted.pdf",
    new PdfOpenOptions
    {
        Password = "owner-demo",
        AllowEditing = true
    });
doc.Save("unencrypted.pdf", new PdfSaveOptions
{
    Encryption = PdfEncryptionAction.Remove
});
using var saved = PdfDocument.Open("unencrypted.pdf");
Console.WriteLine($"Encrypted: {saved.IsEncrypted}");
Text
Encrypted: False

The short answer

Save an editable document with Encryption = PdfEncryptionAction.Set and explicit NewEncryption settings. Supply a nonempty user password if opening the file must require a password. The example writes AES-256 encryption, uses separate user and owner passwords, and records printing as the only permission bit.

The passwords in this downloadable example are demonstration values, not secrets for a production document.

Can you encrypt a PDF with a password?

Yes. OnePDF’s write API supports new AES-128 encryption or AES-256. PdfEncryptionOptions.Cipher defaults to AES-256. Saving with AES-256 upgrades an older file’s declared version to PDF 2.0 under the writer’s version rules, so an older reader must support that encryption to open it; AES-128 requires PDF 1.6.

New encryption requires a full save. Incremental saving supports only Keep, so it cannot be used to introduce a new password or remove the old encryption.

The three save actions are Set, Keep and Remove. Keep is the default: it preserves the existing encryption settings, and a plain input stays plain. Set replaces any existing encryption with the settings you provide. Remove writes the already-open document without encryption.

How do PDF password permissions work?

The user password controls opening the document as a user. The owner password opens it at owner access level. An empty user password allows the file to open without a password, even if the file has encryption and an owner password. An empty or null owner password means the user password is used for both.

Permission flags describe operations such as printing, copying content, modifying annotations, filling forms and assembling pages. PdfPermissions.Print records a printing permission; PrintHighQuality is a separate bit for a faithful high-quality copy. The full program prints the recorded flags after opening with each credential. Owner access does not rewrite those stored flags, which is why the same Print value appears twice.

These flags are not a general restriction against every tool that can read the file. The application consuming the PDF decides whether to honor them. Encryption and permission reporting are different properties: password rejection tests the former, while reading the flags only checks the latter.

Can a password-protected PDF file be unlocked?

Once you can open a document with an accepted password, you can save it with PdfEncryptionAction.Remove, as the variation shows. The resulting file opens without a password and reports IsEncrypted = false. This is not password recovery: it requires the document to be open already.

OnePDF does not offer RC4 for new encryption. It can retain RC4 when keeping the encryption of an existing RC4 file. AES output is intentionally not byte-identical between saves because initialization vectors and salts are random.

Metadata is encrypted by default. Setting EncryptMetadata = false leaves the XMP metadata stream readable without a password; it is a separate choice from whether the page content is encrypted.

All onepdf recipes