PDF Security in C#: How to Digitally Sign, Encrypt and Decrypt your files the proper way
Security is vital when it comes to sharing confidential documents. One of the best solutions to keep PDF files secure is encrypting files or restricting access to some functionalities. This is useful when sharing the document across multiple devices, people, or even the Internet.
If you are using .NET and need to secure your Pdf files in C#, you can use the GemBox.Pdf component. This component allows you to create and validate PDF digital signatures in your C# and VB.NET applications.
This tutorial shows you how to:
- Install and configure the GemBox.Pdf library
- How to protect a PDF file
- How to decrypt a PDF file
- How to digitally sign a PDF file
- How to digitally sign a PDF file with a visible signature
- How to digitally sign a PDF file with multiple signatures
- How to digitally sign a PDF file with a PDF Advanced Electronic Signature (PAdES)
- How to digitally sign a PDF file using a PKCS#11/Cryptoki device
- How to digitally sign a PDF file using an external signature
- How to validate signatures of a digitally signed PDF file
- How to remove existing digital signatures from a PDF file
Install and configure the GemBox.Pdf library
For this article, we propose that you create a new .NET project. If you are unfamiliar with Visual Studio or need a reminder, refer to the official tutorial. Also, although GemBox.Pdf supports a wide range of .NET versions (from .NET Framework 3.5), we recommend that you use the newest version.
Before you can start converting HTML to PDF, you need to install GemBox.Pdf. The best way to do that is via NuGet Package Manager.
In the Solution Explorer window, right-click on the solution and select 'Manage NuGet Packages for Solution'.
Search for GemBox.Pdf and click on 'Install'.
As an alternative, you can open the NuGet Package Manager Console (Tools -> NuGet Package Manager -> Package Manager Console) and run the following command:
Install-Package GemBox.Pdf
Now that you have installed the GemBox.Pdf library, all you have to do is make sure you call the ComponentInfo.SetLicense
method before using any other member of the library. Since we are working with a console application, we propose you put this line at the beginning of the Main()
method.
If you have set everything correctly, your code should look like this:
using GemBox.Pdf;
class Program
{
static void Main()
{
ComponentInfo.SetLicense("FREE-LIMITED-KEY");
// The code starts here
}
}
In this tutorial, we are going to work in the free mode. The free mode allows you to use the library without purchasing a license, but with some limitations. You can read more about working modes and limitations on the Evaluation and Licensing documentation page.
How to protect a PDF file
PDF provides built-in protection that allows you to enforce various user access permissions in a PDF file. In this section, we will present a code that will restrict users to only printing a document and filling in an interactive form if it exists in the file. To add these restrictions, follow the next steps:
- First, load the PDF document from an unencrypted PDF file.
using (var document = PdfDocument.Load("Input.pdf")) { // The rest of the code goes here }
- You need to set password-based encryption and specify the password required to edit a PDF document (remove restrictions).
var encryption = document.SaveOptions.SetPasswordEncryption(); encryption.PermissionsPassword = "owner";
- Define which action(s) the user can make in your file. This specific code enables the user to print and fill in a PDF form without requiring a password.
encryption.Permissions = PdfUserAccessPermissions.Print | PdfUserAccessPermissions.FillForm;
- Finally, save the PDF document to an encrypted PDF file.
document.Save("Protected.pdf");
Note that these permissions are enforced by the end-user PDF viewer/editor. GemBox.Pdf does not respect user access permissions since it is not an end-user application.
How to encrypt a PDF file
PDF encryption is beneficial when you want to allow only people who know the password to view your PDF file. It's also the ideal security measure to prevent unauthorized people from printing or editing this file.
To encrypt a file, you can follow these simple steps:
- First, load the PDF document from an unencrypted PDF file.
- Use
SetPasswordEncryption
andDocumentOpenPassword
to set the password required to open the PDF document. - Save the PDF document to an encrypted PDF file.
using (var document = PdfDocument.Load("Input.pdf"))
{
document.SaveOptions.SetPasswordEncryption().DocumentOpenPassword = "user";
document.Save("Encrypted.pdf");
}
When you execute this code, you will create an encrypted PDF file that can only be opened with the password 'user'.
Note that you can combine PDF encryption with user access permissions. In that case, users need to provide either a DocumentOpenPassword
or a PermissionsPassword
to open the PDF. However, only the ones who provided a PermissionsPassword
will be able to edit the document.
How to Decrypt a PDF file
Decrypting a PDF file with GemBox.Pdf in C# is as simple as setting encryption. Here are detailed instructions:
- To decrypt an encrypted PDF file when loading a PDF document, you must specify the
DocumentOpenPassword
in thePdfLoadOptions.Password
property. - Remove the encryption from the PDF document by clearing the
SaveOptions.Encryption
property. - Save the PDF document to an unencrypted PDF file.
var options = new PdfLoadOptions() { Password = "user" };
using (var document = PdfDocument.Load("Encrypted.pdf", options))
{
document.SaveOptions.Encryption = null;
document.Save("Unencrypted.pdf");
}
If you provide an invalid password, an InvalidPdfPasswordException
will not be thrown immediately. This is because GemBox.Pdf verifies the password only when the first PdfString
or PdfStream
from an encrypted PDF file has to be read, which means that an exception can be thrown after loading a PDF document. Because of that, we suggest that you wrap the encrypted PDF file handling code in a try-catch block.
try
{
var options = new PdfLoadOptions() { Password = "user" };
using (var document = PdfDocument.Load("Encrypted.pdf", options))
{
document.SaveOptions.Encryption = null;
document.Save("Unencrypted.pdf");
}
}
catch (InvalidPdfPasswordException ex)
{
// Gracefully handle the case when the input PDF file is encrypted
// but the provided password is invalid
Console.WriteLine("Invalid password!");
}
How to digitally sign a PDF file
A digital signature is a security mechanism that ensures the integrity of the document (unchanged by anyone other than the author), its authenticity (only edited by an author known to viewers), and its non-repudiation (the author can't deny their authorship).
This section will show how to sign a PDF file digitally. The digital signature is invisible, meaning there isn't a visual representation of the signature on any of the pages. Please refer to the next section if you are looking for visible digital signature code.
Follow these steps to add a digital signature to an existing PDF file in C#:
- After loading the PDF file, add a signature field to the PDF document.
var signatureField = document.Form.Fields.AddSignature();
- Get a digital ID from a certificate (PKCS#12/PFX) file.
var digitalId = new PdfDigitalId("GemBoxRSA1024.pfx", "GemBoxPassword");
- Create a PDF signer that will create the digital signature.
var signer = new PdfSigner(digitalId);
- Since Adobe Acrobat Reader currently doesn't download the certificate chain, you will also need to embed the certificate of intermediate Certificate Authority in the signature. You can learn more about this matter here.
var certificates = new PdfCertificate[] { new PdfCertificate("GemBoxRSA.crt") }; signer.ValidationInfo = new PdfSignatureValidationInfo(certificates, null, null);
- Initiate signing of the PDF file with the specified signer.
signatureField.Sign(signer);
- Finish signing by saving the signature to the PDF file.
document.Save("Digital Signature.pdf");
Here is a screenshot of a PDF file digitally signed using the code above:
How to digitally sign a PDF file with a visible signature
This section will show you how to add a visible digital signature to an existing PDF file. You can see that the code is more complex than the invisible signature code because it needs several adjustments.
To add a visible signature to your PDF files in C#, refer to the step-by-step instructions below.
- After loading a PDF file, add a visible signature field to the first page of the PDF document. Next, retrieve the signature's appearance settings to customize it. The signature appearance will consist of text above an image.
var signatureField = document.Form.Fields.AddSignature(document.Pages[0], 300, 500, 250, 100); var signatureAppearance = signatureField.Appearance; signatureAppearance.TextPlacement = PdfTextPlacement.TextAboveIcon;
- In this case, you will set the text to occupy 40% of the annotation rectangle height. The image will occupy the rest. The text will also be right-aligned.
signatureAppearance.TextExtent = 0.4; signatureAppearance.TextAlignment = PdfTextAlignment.Right;
- Now you will set the font. A zero value for font size means the text is auto-sized to fit the annotation rectangle.
signatureAppearance.Font = new PdfFont("Times New Roman", 0);
- In this part of the code, you will set the 'Reason', 'Location', and 'Date' labels. Set the ones that you don't want to show to
string.Empty
. In the code below, you will hide the 'Date' label by setting it to string.Empty.signatureAppearance.Reason = "Legal agreement between the seller and the buyer about the purchase"; signatureAppearance.Location = "New York, USA"; signatureAppearance.DateFormat = string.Empty;
- In this next part you will set the signature image. It should be scaled only if it is too big to fit. You will also specify that the signature image should dock to the bottom right (x = 1 and y = 0) corner.
signatureAppearance.Icon = PdfImage.Load("GemBoxSignature.png"); signatureAppearance.IconScaleCondition = PdfScaleCondition.ContentTooBig; signatureAppearance.IconAlignment = new PdfPoint(1, 0);
- The rest of the code for digital signing is the same as in the previous section.
var digitalId = new PdfDigitalId("GemBoxRSA1024.pfx", "GemBoxPassword"); var signer = new PdfSigner(digitalId); var certificates = new PdfCertificate[] { new PdfCertificate("GemBoxRSA.crt") }; signer.ValidationInfo = new PdfSignatureValidationInfo(certificates, null, null); signatureField.Sign(signer); document.Save("Digital Signature.pdf");
Here is a screenshot of a PDF file with a visible signature created using GemBox.Pdf.
How to Digitally sign a PDF file with multiple signatures
GemBox.Pdf is also helpful when creating a document that needs more than one signature. For example, a contract in PDF that requires signatures of both the company and the author.
To add two or more signatures to a PDF document in C#, you can refer to the following code:
- After loading an existing PDF file, add a first signature field to the first page of the PDF document, and the first digital ID from a PFX file.
var signatureField1 = document.Form.Fields.AddSignature(document.Pages[0], 100, 500, 200, 50); var digitalId1 = new PdfDigitalId("GemBoxRSA1024.pfx", "GemBoxPassword");
- Create a PDF signer that will create the first signature. Also, embed the certificate of intermediate Certificate Authority in the signature.
var signer1 = new PdfSigner(digitalId1); signer1.ValidationInfo = new PdfSignatureValidationInfo( new PdfCertificate[] { new PdfCertificate("GemBoxRSA.crt") }, null, null);
- Initiate the first signing of the PDF file with the specified signer.
signatureField1.Sign(signer1);
- Finish the first signing by saving it to a new PDF file.
document.Save("Multiple Digital Signature.pdf");
- Add a second signature field to the first page of the PDF document.
var signatureField2 = document.Form.Fields.AddSignature(document.Pages[0], 300, 500, 250, 50);
- Get a second digital ID and create a PDF signer that will generate the second signature.
var digitalId2 = new PdfDigitalId("GemBoxECDsa521.pfx", "GemBoxPassword"); var signer2 = new PdfSigner(digitalId2);
- Once more, you need to embed the certificate of intermediate Certificate Authority in the signature.
signer2.ValidationInfo = new PdfSignatureValidationInfo( new PdfCertificate[] { new PdfCertificate("GemBoxECDsa.crt") }, null, null);
- Initiate the second signing of the PDF file with the specified signer.
signatureField2.Sign(signer2);
- Finish the second signing of the same PDF file (Multiple Digital Signature.pdf).
document.Save();
The following screenshot shows a PDF file containing two revisions (two digital signatures) created by the code above.
How to digitally sign a PDF file with a PDF Advanced Electronic Signature (PAdES)
PDF Advanced Electronic Signature (PAdES) is an electronic signature in a PDF file that meets the requirements set forth by the eIDAS regulation on electronic identification and trust services for electronic transactions in the European Single Market.
With GemBox.Pdf, you can create PAdES baseline signatures of all the following levels in your C# or VB.NET application:
PAdES B-B level
You can use this level for short-term electronic signatures. A PAdES B-B level PDF digital signature must be an advanced electronic signature and include the signer's certificate.
PAdES B-T level
This level is like the B-B level but with a timestamp. A time-based mark proves that the signature existed at a specific date and time.
PAdES B-LT level
This level is similar to the B-T level, but adds validation-related information (OCSP responses or CRLs and all certificates of the certificate chain, from the signer's certificate to the root CA certificate) for the signature to the Document Security Store (DSS) of a PDF document.
B-LT level allows for a signature to be validated, even after a long time, when the signing environment (e.g., signer's Certificate Authority) is no longer available. This level is recommended for Advanced Electronic Signatures.
PAdES B-LTA level
Similar to the B-LT level but adds validation-related information for the signature's timestamp to the DSS and a document timestamp to the PDF document.
B-LTA level may help validate the signature beyond any event that may limit its validity. This level is recommended for Qualified Electronic Signatures.
How to Add PAdES signature to an PDF document
See the following tutorial to learn how to add a PAdES signature, in all the levels we mentioned above. You will notice that the code is similar for most of them, but there will be additional steps for some.
- After loading a PDF document, add a visible signature field to the first page and get a digital ID from a certificate file.
var signatureField = document.Form.Fields.AddSignature(document.Pages[0], 300, 500, 250, 50); var digitalId = new PdfDigitalId("GemBoxECDsa521.pfx", "GemBoxPassword");
- Create a PDF signer that will create a PAdES signature. PdfSigner should create a CAdES-equivalent signature. Also, embed the certificate of intermediate Certificate Authority in the signature.
var signer = new PdfSigner(digitalId); signer.SignatureFormat = PdfSignatureFormat.CAdES; signer.ValidationInfo = new PdfSignatureValidationInfo( new PdfCertificate[] { new PdfCertificate("GemBoxECDsa.crt") }, null, null);
- For the B-T, B-LT, and B-LTA levels, you will need to add this line of code since they require that the PdfSigner embeds a timestamp. In this example, you will use a timestamp created by freeTSA.org.
signer.Timestamper = new PdfTimestamper("https://freetsa.org/tsr");
- Next, you need to specify the signature level. In the code below you will use the PAdES_B_LTA level, but you can use any of the PdfSignatureLevel values supported by GemBox.Pdf.
signer.SignatureLevel = PdfSignatureLevel.PAdES_B_LTA;
- At last, initiate signing of the PDF file with the specified signer and finish signing the PDF file.
signatureField.Sign(signer); document.Save("Output.pdf");
The screenshot below shows a PDF file with a PAdES B-B level signature created with GemBox.Pdf.
And the following screenshot shows a PDF file with a PAdES B-LTA level signature created with GemBox.Pdf.
How to Digitally sign a PDF file using a PKCS#11/Cryptoki device
With GemBox.Pdf, you can digitally sign PDF files in your C# application using a PKCS#11/Cryptoki device that conforms to PKCS#11 specification.
PKCS#11 is one of the Public-Key Cryptography Standards (PKCS) that defines a platform-independent API (called "Cryptoki") for cryptographic devices, such as hardware security modules (HSM), USB Tokens, and smart cards.
Follow this tutorial to digitally sign a PDF file using a Cryptoki device.
- In this code, you will need to use the following namespaces:
using System; using System.IO; using System.Linq; using GemBox.Pdf; using GemBox.Pdf.Forms; using GemBox.Pdf.Security;
- Download and extract the GemBoxPkcs11SoftwareModule.zip package to a directory. Afterward, you will set the environment variable with the path to the configuration file. Note that this is required only for the SoftHSM device used in this tutorial. It is not necessary for your PKCS#11 device.
var pkcs11SoftwareModuleDirectory = "C:\\GemBoxPkcs11SoftwareModule"; Environment.SetEnvironmentVariable("SOFTHSM2_CONF", Path.Combine(pkcs11SoftwareModuleDirectory, "softhsm2.conf"));
- Specify the path to the Cryptoki library, depending on the runtime architecture (64-bit or 32-bit).
var libraryPath = Path.Combine(pkcs11SoftwareModuleDirectory, IntPtr.Size == 8 ? "softhsm2-x64.dll" : "softhsm2.dll");
- Create a new PdfPkcs11Module.
using (var pkcs11Module = new PdfPkcs11Module(libraryPath))
- Get a token from your PKCS#11 device and log in to it so that you can access protected cryptographic functions. You also need to fetch a digital ID from the PKCS#11 device token.
var token = pkcs11Module.Tokens.Single(t => t.TokenLabel == "GemBoxECDsaToken"); token.Login("GemBoxECDsaPin"); var digitalId = token.DigitalIds.Single(id => id.Certificate.SubjectCommonName == "GemBoxECDsa521");
- Load the PDF document that you want to sign with PKCS#11
using (var document = PdfDocument.Load("Reading.pdf"))
- Then you will add a visible signature field to the first page of the PDF document.
var signatureField = document.Form.Fields.AddSignature(document.Pages[0], 300, 500, 250, 50);
- Create a PDF signer and embed the certificate of intermediate Certificate Authority in the signature.
var signer = new PdfSigner(digitalId); var intermediateCA = token.DigitalIds.Single( id => id.Certificate.SubjectCommonName == "GemBoxECDsa").Certificate; signer.ValidationInfo = new PdfSignatureValidationInfo( new PdfCertificate[] { intermediateCA }, null, null);
- Initiate signing with the specified signer and finish by saving the PDF document to a PDF file.
signatureField.Sign(signer); document.Save("Digital Signature PKCS#11.pdf");
- At the end, log out of the PKCS#11 token.
token.Logout();
The image below shows a PDF file signed using a Cryptoki device in C#:
How to digitally sign a PDF file using an external signature
When you need to sign a large number of PDF documents, you can automate this process with GemBox.Pdf instead of doing it manually. GemBox.Pdf allows you to sign PDF documents with an external digital signature created from various sources such as an HSM, USB tokens, and smart cards.
In previous examples, you signed the PDF files using a digitalId created with the PdfDigitalId class through a .pfx file path and password. In this scenario, you will create a new class based on PdfDigitalId that represents a digital ID loaded from an RSA Private Key that is stored inside an XML file.
This class will read the XML file content, store it, and when the signing finally happens, it will use the key to create an instance of RSA, which will be used to sign the signature's hash:
class RSAXmlDigitalId : PdfDigitalId
{
private readonly string privateKeyXmlString;
public RSAXmlDigitalId(string privateKeyXmlFileName, string certificateFileName)
: base(new PdfCertificate(certificateFileName))
{
// Reads and stores the private key string.
this.privateKeyXmlString = System.IO.File.ReadAllText(privateKeyXmlFileName);
}
protected override byte[] SignHash(
byte[] hash, PdfHashAlgorithm hashAlgorithm, PdfRSASignaturePadding rsaSignaturePadding)
{
// Creates a new RSA instance based on the private key string.
using (var rsa = System.Security.Cryptography.RSA.Create())
{
rsa.FromXmlString(this.privateKeyXmlString);
// Signs the hash using the private key.
return rsa.SignHash(hash,
new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm.ToString()),
rsaSignaturePadding == PdfRSASignaturePadding.Pss ?
System.Security.Cryptography.RSASignaturePadding.Pss :
System.Security.Cryptography.RSASignaturePadding.Pkcs1);
}
}
}
The following tutorial shows how to use an external signature to sign your PDF files in C#:
- After loading and adding a visible signature field to the first page of the PDF document, get a digital ID from XML (private key) and certificate files, by using the custom class defined above.
var digitalId = new RSAXmlDigitalId("GemBoxRSA1024PrivateKey.xml", "GemBoxRSA1024.crt");
- Create a PDF signer that will create the digital signature and embed the certificate of intermediate Certificate Authority in the signature.
var signer = new PdfSigner(digitalId); signer.ValidationInfo = new PdfSignatureValidationInfo( new PdfCertificate[] { new PdfCertificate("GemBoxRSA.crt") }, null, null);
- At the end, initiate signing of the PDF document with the specified signer and finish it by saving to a PDF file.
signatureField.Sign(signer); document.Save("External Digital Signature.pdf");
The screenshot below shows a PDF file signed with an external signature:
How to Validate signatures of a digitally signed PDF file
Apart from signing PDF documents, GemBox.Pdf also allows you to validate digital signatures. That way you can check if the document has been modified since the signature was applied and you can verify that the signer's identity is valid.
Before running the following code on your machine, please read the notes on PDF digital signatures.
Follow the next instructions to validate all signatures in a PDF document, in your C# or VB.NET application.
- Load the file using the
PdfDocument.Load
method and get every signature field in the PDF that contains a signature (fields of typePdfFieldType.Signature
where Value != null):var signatureFields = document.Form.Fields .Where(field => field.FieldType == PdfFieldType.Signature) .Cast<PdfSignatureField>() .Where(field => field.Value != null);
- After that, you can iterate on each field and use
Field.Value.Validate()
to check the signature.foreach (var field in signatureFields) { var signature = field.Value; var signatureValidationResult = field.Value.Validate(); if (signatureValidationResult.IsValid) { Console.Write("Signature '{0}' is VALID, signed by '{1}'. ", field.Name, signature.Content.SignerCertificate.SubjectCommonName); Console.WriteLine("The document has not been modified since this signature was applied."); } else { Console.Write("Signature '{0}' is INVALID. ", field.Name); Console.WriteLine("The document has been altered or corrupted since the signature was applied."); } }
Refer to the following image of a PDF signature validation status acquired using GemBox.Pdf.
How to remove existing digital signatures from a PDF file in C#
If you need to remove the digital signatures from an existing PDF document, you can do this with GemBox.Pdf. Just follow the tutorial below.
- First, load the file from which you want to remove signatures.
using (var document = PdfDocument.Load("Contract.pdf"))
- Get a list of all signature fields in the document.
var signatureFields = document.Form.Fields .Where(f => f.FieldType == PdfFieldType.Signature) .Cast<PdfSignatureField>() .ToList();
- You can remove only the signature while keeping the signature field by setting the field value to
null
, or you can fully remove both the signature and field using thedocument.Form.Fields.Remove()
method. For the purpose of demonstration, you will keep every second signature field.for (int i = 0; i < signatureFields.Count; ++i) if (i % 2 == 0) { // Remove signature and keep the field. signatureFields[i].Value = null; } else { // Remove signature and field. document.Form.Fields.Remove(signatureFields[i]); }
- Finally, save the document.
document.Save("Remove Digital Signature.pdf");
The image below shows a PDF document that had a signature field removed. You can see the widget annotation (visual appearance placeholder) in the document where it once was. This signature field can be reused for a new signature in the future. If you decide to delete the signature field, the widget annotation won't appear in the document.
Conclusion
In this guide, you learned various methods for securing PDF documents. You also learned how to validate and remove digital signatures. You should now be able to completely secure your PDF files with whichever method fits best for your PDF documents.
For more information regarding the GemBox.Spreadsheet API, refer to the documentation pages or browse through various runnable examples in our example section.
If you have questions regarding any tutorial in this guide, you can refer to our Forum page or submit a ticket to our technical support.
If you have questions regarding any tutorial in this guide, you can refer to our forum page or submit a ticket to our technical support.