Securing PDF Documents: AES-128 Encryption with TerraPDF vs Other Libraries

Securing PDF Documents: AES-128 Encryption with TerraPDF vs Other Libraries

If you're generating confidential reports, financial statements, or sensitive invoices in .NET, you need encryption. PDFs with passwords. Restricted permissions. Copy-paste protection.

Most developers reach for iText, PdfSharp, or QuestPDF. They work, but they're heavyweight, require external dependencies, or lack clean APIs for permission control.

TerraPDF changes this. With just 5 lines, you get enterprise-grade AES-128 encryption, user/owner passwords, and granular permission flags. No external libraries. No licensing concerns. Zero boilerplate.

The Problem: PDF Encryption Is Messy

Standard PDF libraries make encryption tedious:

Aspect iText PdfSharp QuestPDF TerraPDF
Lines to encrypt 15+ 12+ 8+ 5
Permission control Complex flags Unclear API Basic Fine-grained
External dependencies Yes (bouncy-castle) Yes Optional No
Zero-dependency
AES-128 support

The TerraPDF Way: 5 Lines to Encryption

Document.Create(container =>
{
    container.Encrypt(new EncryptionOptions
    {
        UserPassword  = "confidential",    // Required to open
        OwnerPassword = "admin123",        // Bypass permissions
        Permissions   = PdfPermissions.Print | PdfPermissions.ExtractForAccessibility,
    });

    container.Page(page =>
    {
        page.Size(PageSize.A4);
        page.Margin(2, Unit.Centimetre);
        page.Content().Text("TOP SECRET FINANCIAL REPORT").Bold().FontSize(20);
        page.Content().Text("Encryption: AES-128 | User Password Protected");
    });
})
.PublishPdf("report.pdf");

That's it. The PDF opens in any viewer—Adobe Acrobat, Chrome, Edge, Firefox, Preview—with password protection enforced.

Why This Matters: Permission Granularity

Traditional libraries offer generic "encrypt yes/no" options. TerraPDF gives you fine-grained control:

// View-only: No printing, no copying
container.Encrypt(new EncryptionOptions
{
    UserPassword = "readonly",
    Permissions = PdfPermissions.None,
});

// Allow printing, but not copying or modification
container.Encrypt(new EncryptionOptions
{
    UserPassword = "print_only",
    Permissions = PdfPermissions.Print,
});

// Restrict all except text extraction for accessibility
container.Encrypt(new EncryptionOptions
{
    UserPassword = "access_friendly",
    Permissions = PdfPermissions.ExtractForAccessibility,
});

// Full encryption, no user password, owner-only control
container.Encrypt(new EncryptionOptions
{
    OwnerPassword = "admin",
    Permissions = PdfPermissions.None,   // Viewer opens unlocked but can't print/copy
});

Permission flags available:

Real-World Use Cases

Scenario 1: Confidential Invoices

public byte[] GenerateConfidentialInvoice(Invoice inv)
{
    return Document.Create(container =>
    {
        // Restrict to view and print only—no copying invoice numbers
        container.Encrypt(new EncryptionOptions
        {
            UserPassword = $"inv_{inv.Number}",  // Generate per invoice
            Permissions = PdfPermissions.Print,
        });

        container.Page(page =>
        {
            page.Content().Text($"Invoice #{inv.Number}").Bold().FontSize(18);
            page.Content().Table(t => BuildInvoiceTable(t, inv));
        });
    })
    .PublishPdf();
}

Scenario 2: Internal Reports (Admin-Protected)

var reportPdf = Document.Create(container =>
{
    container.Encrypt(new EncryptionOptions
    {
        OwnerPassword = "C0rp_Admin!2025",   // Only admins can remove restrictions
        UserPassword = null,                  // Opens without password
        Permissions = PdfPermissions.Print,  // Users can only print
    });

    container.Page(page =>
    {
        page.Content().Text("Q1 2025 Financial Summary");
        page.Content().Text("⚠️ Confidential — Print-only, no copy/export allowed");
    });
})
.PublishPdf("q1-report.pdf");

Scenario 3: Public PDFs with Accessibility

container.Encrypt(new EncryptionOptions
{
    UserPassword = "open",
    Permissions = PdfPermissions.ExtractForAccessibility | PdfPermissions.Print,
});
// Users can print and screen readers can extract text,
// but copy-paste from the document is blocked

Under the Hood: Enterprise-Grade Encryption

TerraPDF doesn't cut corners on security:

Algorithm:

What gets encrypted:

What doesn't (per PDF spec):

Zero external dependencies — uses only System.Security.Cryptography:

Comparison: iText vs PdfSharp vs QuestPDF vs TerraPDF

iText Example (boilerplate-heavy)

using iText.Kernel.Pdf;

// Requires external license or AGPL compliance
PdfDocument pdfDocument = new PdfDocument(
    new PdfWriter("document.pdf", 
        new WriterProperties()
            .SetStandardEncryption(
                "userpass".GetBytes(Encoding.UTF8),
                "ownerpass".GetBytes(Encoding.UTF8),
                EncryptionConstants.ALLOW_PRINTING,
                EncryptionConstants.STANDARD_ENCRYPTION_128)));

Document doc = new Document(pdfDocument);
doc.Add(new Paragraph("Hello World"));
doc.Close();

Downsides:

PdfSharp Example (clunky API)

using PdfSharp.Pdf;
using PdfSharp.Pdf.Security;

PdfDocument document = new PdfDocument();
document.SecuritySettings.UserPassword = "user";
document.SecuritySettings.OwnerPassword = "owner";
document.SecuritySettings.PermitAccessibilityExtractContent = true;
document.SecuritySettings.PermitAssembleDocument = false;
document.SecuritySettings.PermitChangeDocument = false;
document.SecuritySettings.PermitCopy = false;
document.SecuritySettings.PermitEditAnnotations = false;
document.SecuritySettings.PermitFillIn = false;
document.SecuritySettings.PermitModifyDocument = false;
document.SecuritySettings.PermitPrint = true;

PdfPage page = document.AddPage();
// ... drawing code
document.Save("document.pdf");

Downsides:

QuestPDF Example (decent, but limited)

Document.Create(container =>
{
    // QuestPDF has basic encryption support
    // but less fine-grained control than TerraPDF
    
    container.Page(page =>
    {
        page.Size(PageSizes.A4);
        page.Content().Text("Encrypted Document");
    });
})
.GeneratePdf("document.pdf");
// Encryption config is limited compared to TerraPDF

Downsides:

TerraPDF (clean, fluent, zero-dependency)

Document.Create(container =>
{
    container.Encrypt(new EncryptionOptions
    {
        UserPassword = "open123",
        OwnerPassword = "admin456",
        Permissions = PdfPermissions.Print | PdfPermissions.CopyText,
    });

    container.Page(page =>
    {
        page.Content().Text("Secure Document");
    });
})
.PublishPdf("document.pdf");

Advantages:

Common Encryption Patterns

View-Only (No Printing or Copying)

container.Encrypt(new EncryptionOptions
{
    UserPassword = "readonly",
    Permissions = PdfPermissions.None,
});

Print-Only (No Copying or Editing)

container.Encrypt(new EncryptionOptions
{
    UserPassword = "print_only",
    Permissions = PdfPermissions.Print,
});

Owner Password Only (No User Password)

container.Encrypt(new EncryptionOptions
{
    OwnerPassword = "admin_only",
    Permissions = PdfPermissions.None,
});
// Document opens freely but can't be printed/copied without owner password

Full Encryption, All Permissions

container.Encrypt(new EncryptionOptions
{
    UserPassword = "secret",
    Permissions = PdfPermissions.All,
});
// Content encrypted but full interactivity allowed

Integration Pattern: Reusable Encryption Component

public class SecureDocument : IComponent
{
    private readonly PdfSecurityLevel _level;
    private readonly string _title;

    public SecureDocument(string title, PdfSecurityLevel level)
    {
        _title = title;
        _level = level;
    }

    public void Compose(IContainer container)
    {
        // Apply encryption based on security level
        container.Encrypt(GetEncryptionOptions(_level));

        container.Page(page =>
        {
            page.Content().Text(_title).Bold().FontSize(20);
            page.Content().Text($"Security Level: {_level}");
        });
    }

    private EncryptionOptions GetEncryptionOptions(PdfSecurityLevel level) => level switch
    {
        PdfSecurityLevel.Public => new() 
        { 
            Permissions = PdfPermissions.All 
        },
        PdfSecurityLevel.Internal => new() 
        { 
            UserPassword = "internal",
            Permissions = PdfPermissions.Print | PdfPermissions.ExtractForAccessibility
        },
        PdfSecurityLevel.Confidential => new() 
        { 
            UserPassword = "confidential",
            OwnerPassword = "admin_override",
            Permissions = PdfPermissions.Print
        },
        _ => throw new ArgumentException("Unknown security level"),
    };
}

public enum PdfSecurityLevel { Public, Internal, Confidential }

// Usage
Document.Create(new SecureDocument("Financial Report", PdfSecurityLevel.Confidential))
    .PublishPdf("report.pdf");

Technical FAQ

Q: Is AES-128 strong enough? A: Yes. AES-128 is approved by NIST and used by government agencies. For standard business documents, it's industry standard. PDF 2.0 also supports AES-256, but PDF 1.7 (TerraPDF's version) uses AES-128.

Q: Can users bypass the encryption? A: No. The user password is required to open. The owner password bypasses permission flags (printing, copying) but the document remains encrypted. There's no "password bypass" mode.

Q: Do all PDF viewers support TerraPDF encryption? A: Yes. Adobe Acrobat, Chrome, Edge, Firefox, Preview (Mac), Foxit, Okular, and nearly all viewers support the PDF 1.7 Standard Security Handler (Revision 4) that TerraPDF uses.

Q: Can I generate a per-user password? A: Yes. Generate passwords dynamically:

var userPassword = $"user_{invoice.CustomerId}_{DateTime.Now:yyyyMMdd}";
container.Encrypt(new EncryptionOptions { UserPassword = userPassword });

Q: What if I only want to encrypt but not require a password? A: Leave UserPassword null and set OwnerPassword. The document opens freely but permissions are enforced.

Why Choose TerraPDF for Encryption

  1. 5-line setup — Clean, fluent API
  2. Zero dependencies — No external packages or native binaries
  3. Fine-grained permissions — 8 distinct permission flags
  4. Production-ready — Enterprise AES-128 encryption
  5. MIT licensed — No licensing restrictions
  6. Universal compatibility — Works in every PDF viewer
  7. Fast — Pure C# with no external calls
  8. Maintainable — Easy to read, test, and update

Conclusion

If you're building .NET applications that generate confidential PDFs—financial reports, invoices, legal documents, medical records—you need encryption.

TerraPDF delivers it with less code, fewer dependencies, and more control than iText, PdfSharp, or QuestPDF.

5 lines. AES-128. All major viewers. MIT license. Zero external packages.

That's the TerraPDF difference.

Get started:

dotnet add package TerraPDF

Documentation: