Securing PDF Files Using .NET SDK and RSA Encryption

Fabio De RoseFabio De Rose
7 min read

Introduction

In today's digital landscape, protecting sensitive documents is a critical task for developers and organizations alike. Whether it's invoices, contracts, or internal documents, ensuring that PDFs are not accessible or editable by unauthorized users is a must. This article presents a practical approach to protect PDF documents using the .NET SDK by Nutrient (formerly known as GdPicture) and to encrypt passwords securely using RSA encryption.

This guide walks through a C# example that performs two tasks:

  1. Secures a PDF with a user and owner password using the .NET SDK

  2. Encrypts the owner password using a public RSA key to protect it before storage or transmission


Why Combine PDF Protection and RSA Encryption?

Password protection on PDFs restricts access and permissions. However, if the passwords themselves are not handled securely, the system remains vulnerable. Encrypting the owner password with RSA ensures that even if someone intercepts the credentials (for example through a network request or in logs), they cannot read or misuse it.

This approach combines document-level security and key management best practices in a single workflow.


Overview of the Workflow

Here is the step-by-step flow implemented in the sample code:

  1. The program prompts the user for the path to a PDF file

  2. It encrypts the owner password using an RSA public key

  3. It loads the PDF using the .NET SDK

  4. It applies both a user password (for opening the file) and an owner password (for editing permissions)

  5. It saves a new encrypted version of the file and displays both the file path and the RSA-encrypted password


Code Walkthrough

Let’s walk through the key parts of the C# implementation.

Step 1: Register the SDK License

new LicenseManager().RegisterKEY("");

Make sure to replace the empty string with your actual license key, a trial key, or leave it empty if having a watermark on your output document doesn’t matter to you.


Step 2: Define RSA Public Key and Get File Input

string publicPemKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...";
Console.Write("Enter the PDF file path: ");
string documentPath = Console.ReadLine();

Here, we define the RSA public key (in base64 PEM format) and prompt the user to input a file path.


Step 3: Encrypt the Owner Password with RSA

string encryptedPassword = EncryptPasswordWithRSA(OwnerPassword, publicPemKey);

The EncryptPasswordWithRSA method handles the encryption using OAEP with SHA-256, which is more secure than the older PKCS#1 padding.

static string EncryptPasswordWithRSA(string password, string base64PemKey)
{
 try
 {
  using var rsa = RSA.Create();
  string pemFormattedKey = "-----BEGIN PUBLIC KEY-----\n" + base64PemKey + "\n-----END PUBLIC KEY-----";
  rsa.ImportFromPem(pemFormattedKey);
  byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
  byte[] encryptedBytes = rsa.Encrypt(passwordBytes, RSAEncryptionPadding.OaepSHA256);
  return Convert.ToBase64String(encryptedBytes);
 }
 catch (Exception ex)
 {
  Console.WriteLine("Error encrypting password: " + ex.Message);
  return null;
 }
}

This output can be stored or transmitted securely.


Step 4: Encrypt the PDF Using .NET SDK

We use the GdPicturePDF class provided by the .NET SDK to open, modify, and save the document with encryption.

static string ProtectPdfWithPassword(string inputPdfPath, string UserPass, string OwnerPass)
{
 GdPicturePDF pdf = new GdPicturePDF();
 string outputPdfPath = Path.Combine(Path.GetDirectoryName(inputPdfPath), "Encrypted_" + Path.GetFileName(inputPdfPath));

 try
 {
  if (pdf.LoadFromFile(inputPdfPath, false) != GdPictureStatus.OK)
  {
   Console.WriteLine("Error loading PDF file.");
   return null;
  }

  PdfEncryption encryption = PdfEncryption.PdfEncryption128BitRC4;

  if (pdf.SaveToFile(outputPdfPath, encryption, UserPass, OwnerPass,
   allowPrint: true, allowCopy: true, allowModify: false,
   allowAnnotate: false, allowFormFilling: true,
   allowContentExtraction: false, allowAccessibilitySupport: true,
   allowDocumentAssembly: true) != GdPictureStatus.OK)
  {
   Console.WriteLine("Error saving encrypted PDF.");
   return null;
  }

  pdf.CloseDocument();
  return outputPdfPath;
 }
 catch (Exception ex)
 {
  Console.WriteLine("Error encrypting PDF: " + ex.Message);
  return null;
 }
}

This method applies 128-bit RC4 encryption, compatible with most PDF readers, while configuring fine-grained permissions.


Output Example

Once the code is executed, here’s a sample output:

Enter the PDF file path: C:\Users\Fabio\Documents\sample.pdf
PDF successfully encrypted and saved as: C:\Users\Fabio\Documents\Encrypted_sample.pdf
Encrypted password (Base64): jleRtq3z+xueRx3nJhF...


Security Considerations

1. Do not store the unencrypted passwords

Passwords, whether user or owner, should never be stored in plain text. If your application needs to transmit or persist passwords, they should always be encrypted, preferably using asymmetric encryption (like RSA) before being saved in a database or sent over the network.

Why it matters:

  • If a data breach occurs and passwords are unencrypted, an attacker can gain immediate access to documents.

  • Encrypting passwords ensures that only the recipient with the private key can decrypt and use them.

  • Even internal logs or temporary files can leak sensitive information if not properly secured.

Best practices:

  • Use RSA public keys to encrypt passwords before storage.

  • Store only the encrypted value and decrypt it only at the moment it's needed, ideally in memory and for the shortest time possible.

2. Use RSA keys of at least 2048 bits

RSA encryption is widely used for secure communication and data protection. However, its strength depends directly on key length.

  • 1024-bit keys are now considered weak and vulnerable to modern attacks.

  • 2048-bit keys offer a good balance between performance and security for most applications.

  • For systems that require high security or are expected to be long-lived, consider 3072 or even 4096-bit keys.

Why it matters:

  • Longer keys drastically increase the time needed for a brute-force attack.

  • Compliance frameworks (such as NIST or ISO 27001) often recommend a minimum of 2048 bits.

Best practices:

  • Always validate the size of the public key when importing it.

  • Use key rotation policies if the same key is reused over long periods.

3. For higher PDF encryption levels, consider AES-256 encryption if supported

The example provided in the article uses RC4 128-bit encryption, which is supported by most PDF readers for compatibility. However, this algorithm is considered less secure by modern standards.

If your application requires strong data protection (for example in finance, healthcare, or government use cases), consider switching to AES-256 encryption, which offers:

  • Stronger protection against brute-force and cryptographic attacks

  • Compliance with security standards like FIPS 140-2, GDPR, HIPAA, etc.

  • Modern cryptographic design, replacing legacy algorithms

Note: Support for AES-256 encryption may depend on the PDF viewer and the SDK version used. Ensure that the clients or systems reading the files can handle this level of encryption.

4. Store private RSA keys securely, preferably in a key vault or HSM

Private keys are the most sensitive component in asymmetric encryption. If compromised, they can be used to decrypt any password or sensitive data encrypted with the matching public key.

Storing them on disk in plain text or inside your codebase is a serious security risk.

Best practices:

  • Use a key vault service such as:

    • Azure Key Vault

    • AWS Key Management Service (KMS)

    • HashiCorp Vault

  • For maximum security, use a Hardware Security Module (HSM) which ensures that private keys never leave the device in plain text.

  • Implement strict access control policies and auditing on who can read or use the key.

Benefits of a key vault or HSM:

  • Centralized key management

  • Enforced encryption-at-rest

  • Built-in logging and rotation mechanisms

  • Regulatory compliance


Full Code

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using GdPicture14;

class Program
{
    static void Main(string[] args)
    {
        new LicenseManager().RegisterKEY("");
        string publicPemKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtdZxy1mHqfJydq+bG8OZ"
                        + "KFPbbA1K/GfXqR4lqCqAYHcK99XNdqz0FBlDWTTmvNTjv3YzWRTzYkvvXlFyYPX/"
                        + "7F8D7T0GyxxXquED9+L1qX+8Acq3pyQJGxe3RZbRnnlhZnDfoqlu3vUpAYqE5XoX"
                        + "b0T6Vx/7iujTvyQezz6LMS9tVuvk+l5fhKHHLXQo2M0e5FwmqMfRZf7Ow5V+fFwV"
                        + "3RkHFAmv8GyT+y4ZWZQg4ybQ+/0yBFMkJzt+id/xBhKY6WbYrPb76RjPjTyDAsFG"
                        + "zp1hbHDEjDkCUZRMqW/NFJxqjRMeLtwf2TpBGGkdrsFGK9K+YbR3Olb8vH89+hYO"
                        + "fwIDAQAB";

        Console.Write("Enter the PDF file path: ");

        string documentPath = Console.ReadLine();
        string UserPassword = "user-pasword";
        string OwnerPassword = "owner-pasword";

        // Encrypt the password using RSA
        string encryptedPassword = EncryptPasswordWithRSA(OwnerPassword, publicPemKey);
        // Protect the PDF with the generated password
        string encryptedPdfPath = ProtectPdfWithPassword(documentPath, UserPassword, OwnerPassword);

        // Display the results
        Console.WriteLine($"PDF successfully encrypted and saved as: {encryptedPdfPath}");
        Console.WriteLine($"Encrypted password (Base64): {encryptedPassword}");
    }
    // Function to encrypt the password using RSA with the given public PEM key
    static string EncryptPasswordWithRSA(string password, string base64PemKey)
    {
        try
        {
            using var rsa = RSA.Create();
            string pemFormattedKey = "-----BEGIN PUBLIC KEY-----\n"
                                   + base64PemKey + "\n"
                                   + "-----END PUBLIC KEY-----";
            rsa.ImportFromPem(pemFormattedKey);
            byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
            byte[] encryptedBytes = rsa.Encrypt(passwordBytes, RSAEncryptionPadding.OaepSHA256);
            return Convert.ToBase64String(encryptedBytes);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error encrypting password: " + ex.Message);
            return null;
        }
    }

    // Function to protect a PDF with a password using .NET SDK
    static string ProtectPdfWithPassword(string inputPdfPath, string UserPass, string OwnerPass)
    {
        GdPicturePDF pdf = new GdPicturePDF();
        string outputPdfPath = Path.Combine(Path.GetDirectoryName(inputPdfPath), "Encrypted_" + Path.GetFileName(inputPdfPath));
        try
        {
            // Load the PDF file
            if (pdf.LoadFromFile(inputPdfPath, false) != GdPictureStatus.OK)
            {
                Console.WriteLine("Error loading PDF file.");
                return null;
            }
            // Choose an encryption
            PdfEncryption encryption = PdfEncryption.PdfEncryption128BitRC4;
            // Save the encrypted PDF
            if (pdf.SaveToFile(outputPdfPath, encryption, UserPass, OwnerPass, true, true, false, false, true, false, true, true) != GdPictureStatus.OK)
            {
                Console.WriteLine("Error saving encrypted PDF.");
                return null;
            }
            // Release resources
            pdf.CloseDocument();
            return outputPdfPath;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error encrypting PDF: " + ex.Message);
            return null;
        }
    }
}

Conclusion

The .NET SDK by Nutrient offers powerful tools to protect PDF files with user and owner passwords. By combining these features with RSA encryption, developers can build secure document workflows that comply with modern security practices.

If you're working with us at Nutrient and need help integrating this into your architecture, feel free to contact me directly at fabio.derose@nutrient.io

Cheers!
Fabio de Rose

0
Subscribe to my newsletter

Read articles from Fabio De Rose directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Fabio De Rose
Fabio De Rose

I love rock music, good wine, and .NET