Test in production without watermarks.
Works wherever you need it to.
Get 30 days of fully functional product.
Have it up and running in minutes.
Full access to our support engineering team during your product trial
In today’s fast-paced digital world, physical paperwork is rapidly being replaced by electronic documents. Whether it’s signing a contract, approving an invoice, or submitting a government form, digital documentation has become the new normal. But with convenience comes a new concern: how do you ensure the authenticity and integrity of those digital documents?
Enter electronic signatures. Much more than a scribble on a touchscreen, digital signatures use cryptographic techniques to verify the signer’s identity and guarantee that the contents of a document haven't been altered. For C# developers, integrating this level of security into PDF workflows is easier than ever—especially with tools like IronPDF and iTextSharp. In this article, we’ll walk through the process of digitally signing PDFs, compare libraries, provide best practices, and help you choose the right solution for your next project.
A digital signature is a cryptographic technique used to validate the authenticity and integrity of a digital message or document. Unlike a simple image-based signature or a typed name, a digital signature uses a private key to encrypt a hash of the document. This encrypted hash can then be verified by anyone using the signer's public key.
Why does this matter? Because it ensures two things:
Authentication – The signature is used to verify PDF documents that came from the stated sender.
Digital signatures are legally binding in many jurisdictions and are vital in industries like finance, healthcare, legal, and government.
PDFs are the standard format for distributing professional documents, from legal contracts to official reports. Adding digital signatures to PDFs serves several critical purposes:
Legality & Compliance: Digital signatures comply with regulations like eIDAS (Europe), ESIGN (U.S.), and others, making them legally recognized.
Security: Signed documents can't be altered without breaking the signature, protecting against tampering or fraud.
Efficiency: No need to print, sign, and scan. Save time and streamline workflows with secure digital approvals.
In short, digital signatures bring trust and efficiency to your document workflows.
When implementing digital signatures in C#, two libraries often stand out: iTextSharp and IronPDF. Both are capable tools, but they cater to different types of developers and project requirements. Let’s break down how they compare in real-world usage.
iTextSharp is a well-known name in the world of PDF manipulation. It’s a part of the broader iText 7 ecosystem, offering extensive support for low-level PDF operations, including cryptographic digital signing.
Developers who need fine-grained control over signature appearance, hashing algorithms, certificate chains, and custom validation workflows will find iTextSharp very capable. It’s highly extensible and designed with complex enterprise needs in mind.
However, that flexibility comes at a cost. The learning curve is steep. Simple tasks, such as adding a visible signature, often require multiple classes, streams, and configuration steps. For new users, this can be overwhelming.
Additionally, iTextSharp is licensed under the AGPL, which requires your application to be open-source unless you purchase a commercial license—a deal-breaker for many closed-source or proprietary projects.
IronPDF, in contrast, takes a modern, developer-first approach. Its API is designed to handle common PDF tasks—like digital signatures, generation, merging, and editing—with minimal setup. What might take a dozen steps in iTextSharp often takes just one or two lines in IronPDF. This makes is a powerful PDF library for .NET framework projects.
For example, signing a PDF in IronPDF doesn’t require working directly with streams or cryptographic settings. You simply load the PDF, call .SignPdf(), and pass in your certificate. It even supports extra metadata like the signer’s location, reason, and contact info—all in a single method call.
Another key benefit is licensing. IronPDF offers a commercial-friendly license without AGPL restrictions, which is ideal for professional and enterprise-grade applications. And while it is a paid product, a generous free trial makes it easy to evaluate before committing.
Feature | iTextSharp | IronPDF |
---|---|---|
Ease of Use | Steep learning curve | Beginner-friendly, minimal code |
License | AGPL (or paid commercial license) | Commercial license with no open-source mandate |
Signature Customization | Highly customizable with cryptography control | Simplified API with optional metadata fields |
Documentation | Detailed, but dense | Clear examples with developer-focused docs |
Best For | Enterprise applications with deep customization | Teams needing rapid implementation and support |
Before diving into digital signature implementations, it’s crucial to understand how to get up and running with each library. Whether you're building an enterprise-grade solution or a quick in-house tool, the right setup can make all the difference.
iTextSharp is the .NET port of the powerful Java-based iText PDF library. To get started, you’ll need to install it via NuGet and reference the right namespaces in your project.
You can install the iTextSharp library into your project with ease through the NuGet Package Manager console. All you need to do is run the following command:
Install-Package iTextSharp
Install-Package iTextSharp
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'Install-Package iTextSharp
This easy installation ensures quick implementation of this library within your C# project.
Once installed, you can start using iTextSharp namespaces in your project:
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
Imports iTextSharp.text.pdf
Imports iTextSharp.text.pdf.security
Keep in mind that iTextSharp is modular. If you plan to use advanced cryptographic features or time stamping, you’ll likely need additional packages like BouncyCastle.Cryptography. This can be installed similarly to iTextSharp, just run the line:
Install-Package BouncyCastle.Cryptography
Install-Package BouncyCastle.Cryptography
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'Install-Package BouncyCastle.Cryptography
Things to Watch For
Licensing: The AGPL license requires any software using iTextSharp to be open-source unless you purchase a commercial license.
Dependencies: Cryptographic operations often require BouncyCastle for certificate handling.
If you’re comfortable configuring these building blocks and need full control over the signing process (e.g., setting appearance, validation level, or timestamping servers), iTextSharp is a solid choice.
IronPDF is a commercial PDF library built with developer productivity in mind. It's designed for .NET developers who want to generate, edit, and sign PDFs with minimal hassle. IronPDF offers a much smoother onboarding experience, especially for those who value clean APIs and quick results.
Install the latest IronPDF package via NuGet:
Install-Package IronPdf
Install-Package IronPdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'Install-Package IronPdf
Or use the .NET CLI:
dotnet add package IronPdf
dotnet add package IronPdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'dotnet add package IronPdf
Start by importing the main IronPDF namespace:
using IronPdf;
using IronPdf;
Imports IronPdf
That’s it—you’re ready to load a PDF and start adding digital signatures.
IronPDF manages everything internally: certificate loading, visible signature positioning, metadata, and final export. You don’t have to manage PDF streams or cryptographic algorithms manually, which is a huge advantage for rapid development.
Key Advantages for Beginners
All-in-One: No extra dependencies or cryptography libraries needed.
No AGPL worries: IronPDF offers a perpetual license and a generous free trial.
You’ll need a .pfx digital certificate file and a password. These are used to generate the digital signature. You can obtain a certificate from a trusted Certificate Authority (CA) or generate one for internal use using tools like OpenSSL.
Include the necessary namespaces
First, we need to ensure we have the correct using statements at the top of the code in order to access the various classes and methods required to sign a PDF digitally with iTextSharp.
using System;
using System.IO;
using System.Linq;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using System;
using System.IO;
using System.Linq;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
Imports System
Imports System.IO
Imports System.Linq
Imports iTextSharp.text.pdf
Imports iTextSharp.text.pdf.security
Imports Org.BouncyCastle.Crypto
Imports Org.BouncyCastle.Pkcs
Define Input PDF and Load it into PdfReader
We the specify the path to the existing PDF and loading it into a PdfReader. We will also assign some string variables that will be used later in the code.
// Path to the unsigned PDF you want to sign
string filename = "example.pdf";
// Load the existing PDF into a reader
PdfReader pdfReader = new PdfReader(filename);
string reason = "Digital Signature Reason";
string location = "Digital Signature Location";
// Path to the unsigned PDF you want to sign
string filename = "example.pdf";
// Load the existing PDF into a reader
PdfReader pdfReader = new PdfReader(filename);
string reason = "Digital Signature Reason";
string location = "Digital Signature Location";
' Path to the unsigned PDF you want to sign
Dim filename As String = "example.pdf"
' Load the existing PDF into a reader
Dim pdfReader As New PdfReader(filename)
Dim reason As String = "Digital Signature Reason"
Dim location As String = "Digital Signature Location"
Define Certificate Path and Password
Next, we point to the .pfx certificate file and provide the password used to protect it.
// Path to your .pfx certificate file (must contain private key)
string pfxFilePath = "certificate-file.pfx";
// Password for the certificate (make sure to protect this securely!)
string pfxPassword = "Password";
// Path to your .pfx certificate file (must contain private key)
string pfxFilePath = "certificate-file.pfx";
// Password for the certificate (make sure to protect this securely!)
string pfxPassword = "Password";
' Path to your .pfx certificate file (must contain private key)
Dim pfxFilePath As String = "certificate-file.pfx"
' Password for the certificate (make sure to protect this securely!)
Dim pfxPassword As String = "Password"
Load the .PFX Certificate Using Pkcs12Store
We use BouncyCastle to load the certificate and private key into a secure store.
// Initialize a new PKCS#12 key store (used for handling the PFX certificate)
Pkcs12StoreBuilder Pkcs12StoreBuilder = new Pkcs12StoreBuilder();
Pkcs12Store pfxKeyStore = Pkcs12StoreBuilder.Build();
// Load the certificate and private key from the PFX file
using (FileStream pfxStream = new FileStream(pfxFilePath, FileMode.Open, FileAccess.Read))
{
// Load into the key store using the provided password
pfxKeyStore.Load(pfxStream, pfxPassword.ToCharArray());
}
// Initialize a new PKCS#12 key store (used for handling the PFX certificate)
Pkcs12StoreBuilder Pkcs12StoreBuilder = new Pkcs12StoreBuilder();
Pkcs12Store pfxKeyStore = Pkcs12StoreBuilder.Build();
// Load the certificate and private key from the PFX file
using (FileStream pfxStream = new FileStream(pfxFilePath, FileMode.Open, FileAccess.Read))
{
// Load into the key store using the provided password
pfxKeyStore.Load(pfxStream, pfxPassword.ToCharArray());
}
' Initialize a new PKCS#12 key store (used for handling the PFX certificate)
Dim Pkcs12StoreBuilder As New Pkcs12StoreBuilder()
Dim pfxKeyStore As Pkcs12Store = Pkcs12StoreBuilder.Build()
' Load the certificate and private key from the PFX file
Using pfxStream As New FileStream(pfxFilePath, FileMode.Open, FileAccess.Read)
' Load into the key store using the provided password
pfxKeyStore.Load(pfxStream, pfxPassword.ToCharArray())
End Using
Prepare PdfStamper for Adding a Signature
A PdfStamper lets us apply a digital signature while preserving the original content.
// Create a PdfStamper that enables signing and appends the signature to the document
PdfStamper pdfStamper = PdfStamper.CreateSignature(
pdfReader,
new FileStream("MyPDF_Signed.pdf", FileMode.Create), // Output path
'\0', // PDF version (unchanged)
null, // Temp file path (optional)
true // Append mode (preserves original content)
);
// Create a PdfStamper that enables signing and appends the signature to the document
PdfStamper pdfStamper = PdfStamper.CreateSignature(
pdfReader,
new FileStream("MyPDF_Signed.pdf", FileMode.Create), // Output path
'\0', // PDF version (unchanged)
null, // Temp file path (optional)
true // Append mode (preserves original content)
);
Imports Microsoft.VisualBasic
' Create a PdfStamper that enables signing and appends the signature to the document
Dim pdfStamper As PdfStamper = PdfStamper.CreateSignature(pdfReader, New FileStream("MyPDF_Signed.pdf", FileMode.Create), ControlChars.NullChar, Nothing, True)
Customize the Signature Appearance
Now we define how and where the signature will appear visually in the document.
// Access the signature appearance settings
PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
// Add optional metadata (shows up in PDF signature details)
signatureAppearance.Reason = reason;
signatureAppearance.Location = location;
// Position the visible signature on the page (x, y, width, height in points)
float x = 360;
float y = 130;
signatureAppearance.Acro6Layers = false; // Use compact signature appearance
signatureAppearance.Layer4Text = PdfSignatureAppearance.questionMark; // Custom label text
signatureAppearance.SetVisibleSignature(
new iTextSharp.text.Rectangle(x, y, x + 150, y + 50), // Rectangle position
1, // Page number
"signature" // Field name
);
// Access the signature appearance settings
PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
// Add optional metadata (shows up in PDF signature details)
signatureAppearance.Reason = reason;
signatureAppearance.Location = location;
// Position the visible signature on the page (x, y, width, height in points)
float x = 360;
float y = 130;
signatureAppearance.Acro6Layers = false; // Use compact signature appearance
signatureAppearance.Layer4Text = PdfSignatureAppearance.questionMark; // Custom label text
signatureAppearance.SetVisibleSignature(
new iTextSharp.text.Rectangle(x, y, x + 150, y + 50), // Rectangle position
1, // Page number
"signature" // Field name
);
' Access the signature appearance settings
Dim signatureAppearance As PdfSignatureAppearance = pdfStamper.SignatureAppearance
' Add optional metadata (shows up in PDF signature details)
signatureAppearance.Reason = reason
signatureAppearance.Location = location
' Position the visible signature on the page (x, y, width, height in points)
Dim x As Single = 360
Dim y As Single = 130
signatureAppearance.Acro6Layers = False ' Use compact signature appearance
signatureAppearance.Layer4Text = PdfSignatureAppearance.questionMark ' Custom label text
signatureAppearance.SetVisibleSignature(New iTextSharp.text.Rectangle(x, y, x + 150, y + 50), 1, "signature")
Extract the Private Key and Sign the PDF
We retrieve the alias (name) of the certificate entry that contains the private key. If the alias exists, we proceed to generate and embed the digital signature using SHA-256.
// Find the first alias in the PFX that has a private key entry
string alias = pfxKeyStore.Aliases.Cast<string>().FirstOrDefault(
entryAlias => pfxKeyStore.IsKeyEntry(entryAlias)
);
// Ensure a valid alias (certificate) was found
if (alias != null)
{
// Retrieve the private key for signing
ICipherParameters privateKey = pfxKeyStore.GetKey(alias).Key;
// Create a signer using SHA-256 and the private key
IExternalSignature pks = new PrivateKeySignature(privateKey, DigestAlgorithms.SHA256);
// Perform the digital signing operation using CMS format
MakeSignature.SignDetached(
signatureAppearance, // Signature appearance
pks, // External signature handler
new Org.BouncyCastle.X509.X509Certificate[] {
pfxKeyStore.GetCertificate(alias).Certificate
}, // Certificate chain (basic single-cert example)
null, null, null, // Optional CRL, OCSP, TSA
0, // Estimated size for the signature (0 = auto)
CryptoStandard.CMS // Signature standard (CMS vs CAdES)
);
}
else
{
Console.WriteLine("Private key not found in the PFX certificate.");
}
// Find the first alias in the PFX that has a private key entry
string alias = pfxKeyStore.Aliases.Cast<string>().FirstOrDefault(
entryAlias => pfxKeyStore.IsKeyEntry(entryAlias)
);
// Ensure a valid alias (certificate) was found
if (alias != null)
{
// Retrieve the private key for signing
ICipherParameters privateKey = pfxKeyStore.GetKey(alias).Key;
// Create a signer using SHA-256 and the private key
IExternalSignature pks = new PrivateKeySignature(privateKey, DigestAlgorithms.SHA256);
// Perform the digital signing operation using CMS format
MakeSignature.SignDetached(
signatureAppearance, // Signature appearance
pks, // External signature handler
new Org.BouncyCastle.X509.X509Certificate[] {
pfxKeyStore.GetCertificate(alias).Certificate
}, // Certificate chain (basic single-cert example)
null, null, null, // Optional CRL, OCSP, TSA
0, // Estimated size for the signature (0 = auto)
CryptoStandard.CMS // Signature standard (CMS vs CAdES)
);
}
else
{
Console.WriteLine("Private key not found in the PFX certificate.");
}
' Find the first alias in the PFX that has a private key entry
Dim [alias] As String = pfxKeyStore.Aliases.Cast(Of String)().FirstOrDefault(Function(entryAlias) pfxKeyStore.IsKeyEntry(entryAlias))
' Ensure a valid alias (certificate) was found
If [alias] IsNot Nothing Then
' Retrieve the private key for signing
Dim privateKey As ICipherParameters = pfxKeyStore.GetKey([alias]).Key
' Create a signer using SHA-256 and the private key
Dim pks As IExternalSignature = New PrivateKeySignature(privateKey, DigestAlgorithms.SHA256)
' Perform the digital signing operation using CMS format
MakeSignature.SignDetached(signatureAppearance, pks, New Org.BouncyCastle.X509.X509Certificate() { pfxKeyStore.GetCertificate([alias]).Certificate }, Nothing, Nothing, Nothing, 0, CryptoStandard.CMS)
Else
Console.WriteLine("Private key not found in the PFX certificate.")
End If
Finalize the Document
Finally, we close the stamper to complete the signing process and write the signed PDF to disk.
// Close the stamper to save and finalize the signed PDF
pdfStamper.Close();
// Close the stamper to save and finalize the signed PDF
pdfStamper.Close();
' Close the stamper to save and finalize the signed PDF
pdfStamper.Close()
Include the necessary namespaces
We start by importing the necessary namespaces for working with PDF signing, certificate handling, and image positioning.
using IronPdf;
using IronPdf.Signing;
using IronSoftware.Drawing;
using System.Security.Cryptography.X509Certificates;
using IronPdf;
using IronPdf.Signing;
using IronSoftware.Drawing;
using System.Security.Cryptography.X509Certificates;
Imports IronPdf
Imports IronPdf.Signing
Imports IronSoftware.Drawing
Imports System.Security.Cryptography.X509Certificates
Load the PDF you want to sign
We load an existing PDF file from disk using IronPDF's simple PdfDocument API. You can also create a new PDF document for this task.
var pdf = PdfDocument.FromFile("example.pdf");
var pdf = PdfDocument.FromFile("example.pdf");
Dim pdf = PdfDocument.FromFile("example.pdf")
Load the PFX certificate used for signing
We load the .pfx certificate containing the private key. The Exportable flag is required so the signing key can be accessed.
X509Certificate2 cert = new X509Certificate2(
"IronSoftware.pfx",
"Password",
X509KeyStorageFlags.Exportable
);
X509Certificate2 cert = new X509Certificate2(
"IronSoftware.pfx",
"Password",
X509KeyStorageFlags.Exportable
);
Dim cert As New X509Certificate2("IronSoftware.pfx", "Password", X509KeyStorageFlags.Exportable)
Create a new PdfSignature using the certificate
We create a new PdfSignature object from the loaded certificate.
var sig = new PdfSignature(cert);
var sig = new PdfSignature(cert);
Dim sig = New PdfSignature(cert)
Apply the signature and save the output
We digitally sign the PDF and save the signed PDF document as a new file.
pdf.Sign(sig);
pdf.SaveAs("signed.pdf");
pdf.Sign(sig);
pdf.SaveAs("signed.pdf");
pdf.Sign(sig)
pdf.SaveAs("signed.pdf")
Output
IronPDF keeps the signing process simple and readable. You load a PDF, provide a certificate, and call SignPdf(). Optional metadata (contact, location, reason) adds professionalism.
Summary: With just a few lines of code, IronPDF makes it incredibly easy to apply digital signatures using standard .pfx certificates — no low-level cryptography required. This makes it easier to implement when compared to the more lengthy code required by libraries such as iTextSharp to handle the same task.
Legal Teams: Automatically sign contracts as they’re generated from templates.
Finance: Digitally sign invoices and reports to prevent tampering.
To get the most from your digital signing implementation:
Use Strong Certificates: Choose 2048-bit RSA keys or stronger.
Keep Private Keys Safe: Store certificates securely, ideally in a hardware security module (HSM).
Timestamp Your Signatures: Add a trusted timestamp to ensure the signature remains valid even after the certificate expires.
Verify Signatures: Include validation in your application to detect tampering or expired certs.
Adding digital signatures to PDF documents is no longer a luxury—it’s a necessity in today’s security-conscious digital landscape. Whether you’re protecting contracts, invoices, reports, or legal documents, having a tamper-evident signature backed by a trusted certificate ensures your files maintain their authenticity and integrity.
In this article, we explored two powerful approaches to PDF signing in C#:
iTextSharp, which gives you low-level cryptographic control and flexibility but requires more boilerplate and familiarity with BouncyCastle.
Both tools support secure .pfx certificates, but IronPDF clearly simplifies the workflow—ideal for .NET developers who want to spend less time handling cryptographic primitives and more time delivering business value.
If you haven't already, consider downloading a free trial of IronPDF and try signing your own PDFs in just a few lines of code. The productivity gains alone are worth the switch, especially when working on time-sensitive projects.