Firmar digitalmente un documento PDF

Chaknith Bin
Chaknith Bin
25 de enero, 2023
Actualizado 24 de diciembre, 2024
Compartir:
This article was translated from English: Does it need improvement?
Translated
View the article in English

Desambiguación importante: Firmar un PDF

Los desarrolladores suelen preguntar cómo pueden añadir mediante programación una firma a un documento PDF utilizando IronPDF. Por lo general, firmar significa cosas diferentes para distintos desarrolladores:

  1. Para firmar digitalmente un documento PDF con un certificado y garantizar que no pueda ser alterado.

  2. Para añadir una imagen de firma manuscrita gráfica a un PDF existente desde un archivo de imagen.

  3. Para estampar la imagen de un certificado en un PDF.

  4. Para agregar un campo de formulario de firma a un PDF que algunos visualizadores pueden solicitar para firmar.

    Comience con IronPDF

    Comience a usar IronPDF en su proyecto hoy con una prueba gratuita.

    Primer Paso:
    green arrow pointer


Firmar un PDF con un certificado digital

IronPDF admite muchas formas de firmar un PDF con un certificado de firma digital en formatos .pfx y .p12. En esta guía práctica, se le guiará a través de los tres métodos principales utilizados para firmar digitalmente documentos PDF:

Signing MethodDescription
SignSign a PDF with a PdfSignature object
SignWithFileSign PDF with a digital signature certificate(.pfx or .p12) on disk
SignWithStoreSigns the PDF with digital signature extracted from your computer's signature storage. Based on a thumbprint ID

Archivos de certificado de firma digital admitidos

Cumplimos oficialmente con el estándar X509Certificate2 y admitimos firmas .pfx y .p12. Si su firma no se puede aplicar directamente en los métodos de firma de IronPDF, necesitará crear un certificado X509Certificate2 con instrucciones que se pueden encontrar en la documentación de Microsoft.

Firmar: Crear FirmaPdf a partir de X509Certificado2

Los métodos de firma de IronPDF aceptarán objetos X509Certificate2 con X509KeyStorageFlags configurados como Exportable.

Atención

  • IronPDF solo admite X509KeyStorageFlags.Exportable. Algunos certificados tienen KeyStorageFlags establecido en Exportable por defecto. Intentar usar diferentes KeyStorageFlags resultará en una excepción => Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'The requested operation is not supported.'

:path=/static-assets/pdf/content-code-examples/how-to/signing-X509Certificate2-with-privatekey.cs
using IronPdf;
using IronPdf.Signing;
using System.Security.Cryptography.X509Certificates;

ChromePdfRenderer renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>foo</h1>");

// Create X509Certificate2 object with X509KeyStorageFlags set to Exportable
X509Certificate2 cert = new X509Certificate2("IronSoftware.pfx", "123456", X509KeyStorageFlags.Exportable);

// Create PdfSignature object
var sig = new PdfSignature(cert);

// Sign PDF document
pdf.Sign(sig);

pdf.SaveAs("signed.pdf");
Imports IronPdf
Imports IronPdf.Signing
Imports System.Security.Cryptography.X509Certificates

Private renderer As New ChromePdfRenderer()
Private pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>foo</h1>")

' Create X509Certificate2 object with X509KeyStorageFlags set to Exportable
Private cert As New X509Certificate2("IronSoftware.pfx", "123456", X509KeyStorageFlags.Exportable)

' Create PdfSignature object
Private sig = New PdfSignature(cert)

' Sign PDF document
pdf.Sign(sig)

pdf.SaveAs("signed.pdf")
$vbLabelText   $csharpLabel

Sign: Añadir detalles granulares a PdfSignature

Al instanciar PdfSignature o una vez instanciado, se puede añadir información útil al objeto PdfSignature, incluida la fecha, el contacto de firma, la ubicación, el motivo de la firma, la marca de tiempo y la adición de una imagen como apariencia visual en el documento PDF.

Consejos
Compatible con servidores de sellado de tiempo que requieren SHA256 y SHA512

:path=/static-assets/pdf/content-code-examples/how-to/signing-add-granular-information.cs
using IronPdf;
using IronPdf.Signing;
using IronSoftware.Drawing;
using System;

ChromePdfRenderer renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>foo</h1>");

pdf.SaveAs("signed.pdf");

// Create PdfSignature object
var sig = new PdfSignature("IronSoftware.pfx", "123456");

// Add granular information
sig.SignatureDate = new DateTime(2000, 12, 02);
sig.SigningContact = "IronSoftware";
sig.SigningLocation = "Chicago";
sig.SigningReason = "How to guide";
sig.TimestampHashAlgorithm = TimestampHashAlgorithms.SHA256;
sig.TimeStampUrl = "http://timestamp.digicert.com";
sig.SignatureImage = new PdfSignatureImage("IronSoftware.png", 0, new Rectangle(0, 600, 100, 100));

// Sign and save PDF document
sig.SignPdfFile("signed.pdf");
Imports IronPdf
Imports IronPdf.Signing
Imports IronSoftware.Drawing
Imports System

Private renderer As New ChromePdfRenderer()
Private pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>foo</h1>")

pdf.SaveAs("signed.pdf")

' Create PdfSignature object
Dim sig = New PdfSignature("IronSoftware.pfx", "123456")

' Add granular information
sig.SignatureDate = New DateTime(2000, 12, 02)
sig.SigningContact = "IronSoftware"
sig.SigningLocation = "Chicago"
sig.SigningReason = "How to guide"
sig.TimestampHashAlgorithm = TimestampHashAlgorithms.SHA256
sig.TimeStampUrl = "http://timestamp.digicert.com"
sig.SignatureImage = New PdfSignatureImage("IronSoftware.png", 0, New Rectangle(0, 600, 100, 100))

' Sign and save PDF document
sig.SignPdfFile("signed.pdf")
$vbLabelText   $csharpLabel

Demostración

Es posible que aparezca un signo de exclamación o de advertencia en lugar de una marca de verificación. Esto ocurre porque Adobe no puede confirmar la autenticidad e integridad del documento al no estar presente el certificado. Para obtener la marca de verificación, añada el certificado a Adobe y vuelva a abrir el documento.

Diferentes formas de añadir imágenes

La imagen puede incluirse de muchas maneras:

  • Establece la propiedad SignatureImage en un nuevo objeto PdfSignatureImage.
  • Utilice el método LoadSignatureImageFromFile para cargar una imagen desde un archivo. El método LoadSignatureImageFromFile admite varios formatos de imagen.
  • Use el método LoadSignatureImageFromStream para cargar la imagen desde el flujo. El flujo de imágenes puede generarse a partir de otras bibliotecas siempre que tenga los formatos TGA, PBM, TIFF, BMP, GIF, PNG, JPEG, Webp.
:path=/static-assets/pdf/content-code-examples/how-to/signing-add-image.cs
using IronPdf.Signing;
using IronSoftware.Drawing;

// Create PdfSignature object
var sig = new PdfSignature("IronSoftware.pfx", "123456");

// Add image by property
sig.SignatureImage = new PdfSignatureImage("IronSoftware.png", 0, new Rectangle(0, 600, 100, 100));

// Add image by LoadSignatureImageFromFile method
sig.LoadSignatureImageFromFile("IronSoftware.png", 0, new Rectangle(0, 600, 100, 100));

// Import image using IronSoftware.Drawing
AnyBitmap image = AnyBitmap.FromFile("IronSoftware.png");

sig.LoadSignatureImageFromStream(image.ToStream(), 0, new Rectangle(0, 600, 100, 100));
Imports IronPdf.Signing
Imports IronSoftware.Drawing

' Create PdfSignature object
Private sig = New PdfSignature("IronSoftware.pfx", "123456")

' Add image by property
sig.SignatureImage = New PdfSignatureImage("IronSoftware.png", 0, New Rectangle(0, 600, 100, 100))

' Add image by LoadSignatureImageFromFile method
sig.LoadSignatureImageFromFile("IronSoftware.png", 0, New Rectangle(0, 600, 100, 100))

' Import image using IronSoftware.Drawing
Dim image As AnyBitmap = AnyBitmap.FromFile("IronSoftware.png")

sig.LoadSignatureImageFromStream(image.ToStream(), 0, New Rectangle(0, 600, 100, 100))
$vbLabelText   $csharpLabel

Permisos de firma

Puede especificar explícitamente las condiciones de validez de su certificado. Si desea que su firma quede invalidada ante cualquier cambio, o que sólo se permitan cambios en los campos del formulario, etc., utilice la siguiente tabla para ver las opciones:

No se permiten cambios

Este parámetro es opcional y si no se establece se aplicará una firma que certifica una revisión específica y no puede ser invalidada.

Guardar y firmar una iteración de revisión en PDF

En el siguiente ejemplo, abrimos un archivo PDF, realizamos varias ediciones y, antes de guardarlo, lo firmamos. En cuanto a los permisos de firma, sólo permitiremos rellenar formularios como futuras ediciones; de lo contrario, la firma quedará invalidada por cualquier otra edición.

Luego llamaremos a SaveAsRevision para guardar la revisión en el historial y luego guardar nuestro nuevo documento en el disco.

:path=/static-assets/pdf/content-code-examples/how-to/signing-revision.cs
using IronPdf;
using IronPdf.Rendering;

// Import PDF and enable TrackChanges
PdfDocument pdf = PdfDocument.FromFile("annual_census.pdf", TrackChanges: ChangeTrackingModes.EnableChangeTracking);
// ... various edits ...
pdf.SignWithFile("/assets/IronSignature.p12", "password", null, IronPdf.Signing.SignaturePermissions.AdditionalSignaturesAndFormFillingAllowed);

PdfDocument pdfWithRevision = pdf.SaveAsRevision();

pdfWithRevision.SaveAs("annual_census_2.pdf");
Imports IronPdf
Imports IronPdf.Rendering

' Import PDF and enable TrackChanges
Private pdf As PdfDocument = PdfDocument.FromFile("annual_census.pdf", TrackChanges:= ChangeTrackingModes.EnableChangeTracking)
' ... various edits ...
pdf.SignWithFile("/assets/IronSignature.p12", "password", Nothing, IronPdf.Signing.SignaturePermissions.AdditionalSignaturesAndFormFillingAllowed)

Dim pdfWithRevision As PdfDocument = pdf.SaveAsRevision()

pdfWithRevision.SaveAs("annual_census_2.pdf")
$vbLabelText   $csharpLabel

Comprender el ahorro incremental para las firmas

Mientras que algunos visores, como los navegadores Chrome, solo muestran una versión, los archivos PDF tienen la capacidad de almacenar versiones anteriores del documento, de forma similar al historial de commits de Git. Lo verá en visores de PDF más avanzados, como Adobe Acrobat.

Cuando se trata de firmas de PDF, es importante saber esto porque la acción de firmar un PDF se aplica a la iteración actual del PDF. Su PDF puede tener firmas de iteraciones anteriores, o puede tener algunas versiones sin firmar. Podemos visualizar un ejemplo de la siguiente manera:

PDF Document IterationCertificate ACertificate BCertificate CCertificate D
0 (first save)
1
2
3
(form field edits only)

(form field edits only)
4 (only form fields edited)
5
(no further edits allowed)

(no further edits allowed)

(no further edits allowed)

Arriba tenemos documentos que han pasado por 6 iteraciones diferentes. Este documento puede estar pasando por los departamentos de una empresa con aprobación hasta ser finalizado en la iteración 3. En esta iteración, tanto la Persona A como la Persona B firmaron el documento con el permiso "Sólo edición de campos de formulario". Esto significa que se permite rellenar los campos del formulario en el documento PDF, pero cualquier otro cambio en el documento invalidará sus firmas.

En el ejemplo anterior, podemos suponer que la Persona C es la que ha rellenado el formulario y lo ha devuelto a las Personas A, B y D, que han firmado el documento una última vez con el permiso "No se permiten ediciones". Dado que no se realizaron acciones que invaliden este documento, cuando ejecutemos el método de firma de IronPDF, obtendremos true.

Volver a una revisión anterior

Para revertir a una revisión anterior de un PDF, puedes usar el método GetRevision. Esto olvidará cualquier cambio realizado desde esta revisión, incluidas las firmas más recientes. Para ello, utilice:

:path=/static-assets/pdf/content-code-examples/how-to/signing-revert-revision.cs
using IronPdf;

PdfDocument pdf = PdfDocument.FromFile("report.pdf");

int versions = pdf.RevisionCount; // total revisions

PdfDocument rolledBackPdf = pdf.GetRevision(2);
rolledBackPdf.SaveAs("report-draft.pdf");
Imports IronPdf

Private pdf As PdfDocument = PdfDocument.FromFile("report.pdf")

Private versions As Integer = pdf.RevisionCount ' total revisions

Private rolledBackPdf As PdfDocument = pdf.GetRevision(2)
rolledBackPdf.SaveAs("report-draft.pdf")
$vbLabelText   $csharpLabel

Eliminar firmas

IronPDF tiene un método RemoveSignatures que eliminará todas las firmas de cada revisión de un documento PDF. El uso es el siguiente:

:path=/static-assets/pdf/content-code-examples/how-to/signing-remove-signature.cs
using IronPdf;

PdfDocument pdf = PdfDocument.FromFile("invoice.pdf");
pdf.RemoveSignatures();
Imports IronPdf

Private pdf As PdfDocument = PdfDocument.FromFile("invoice.pdf")
pdf.RemoveSignatures()
$vbLabelText   $csharpLabel

Verificar todas las firmas de un PDF

Al llamar al método de verificación de firmas en un documento PDF, se examinarán todas las firmas de todas las iteraciones del documento y se comprobará que siguen siendo válidas. Esto devolverá un bool de true si todos son válidos.

:path=/static-assets/pdf/content-code-examples/how-to/signing-verify-signatures.cs
using IronPdf;

PdfDocument pdf = PdfDocument.FromFile("annual_census.pdf");
bool isValid = pdf.VerifyPdfSignatures();
Imports IronPdf

Private pdf As PdfDocument = PdfDocument.FromFile("annual_census.pdf")
Private isValid As Boolean = pdf.VerifyPdfSignatures()
$vbLabelText   $csharpLabel

Estampar una firma en un PDF

En primer lugar, empezaré con un PDF que quiero firmar. Utilizaré esta factura de ejemplo:

Aplicaremos una firma manuscrita que está en forma de una imagen .png a nuestro PDF. Puede ser una firma manuscrita o la imagen que se utilizó en la creación de un archivo de certificado. Este es el ejemplo de firma que utilizaremos:

Signature related to Estampar una firma en un PDF

Código

Para ello, utilizaremos el siguiente código para estampar la firma manuscrita en el PDF a modo de marca de agua:

:path=/static-assets/pdf/content-code-examples/how-to/signing-handwritten.cs
using IronPdf;
using IronPdf.Editing;

var pdf = PdfDocument.FromFile("invoice.pdf");

pdf.ApplyWatermark("<img src='signature.png'/>", 90, VerticalAlignment.Bottom, HorizontalAlignment.Right);

pdf.SaveAs("official_invoice.pdf");
Imports IronPdf
Imports IronPdf.Editing

Private pdf = PdfDocument.FromFile("invoice.pdf")

pdf.ApplyWatermark("<img src='signature.png'/>", 90, VerticalAlignment.Bottom, HorizontalAlignment.Right)

pdf.SaveAs("official_invoice.pdf")
$vbLabelText   $csharpLabel

Salida Resultado

Después de ejecutar este código, tenemos este archivo de salida que tiene nuestra firma en la parte inferior derecha:


Añadir un campo de firma sin firmar a un PDF

Para añadir un campo de formulario de firma sin firmar o vacío, primero debe crear el campo de formulario de firma instanciando el objeto de firma. A continuación, en el documento PDF de destino, acceda a la propiedad Form y pase el objeto de firma recién creado al método Add. Finalmente, exporta el PDF con el formulario de firma vacío.

:path=/static-assets/pdf/content-code-examples/how-to/signing-unsigned-signature.cs
using IronPdf;
using IronSoftware.Forms;

ChromePdfRenderer renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>testing</h1>");

// Configure required parameters
string name = "cert";
uint pageIndex = 0;
double x = 100;
double y = 600;
double width = 300;
double height = 100;

// Create signature
SignatureFormField signature = new SignatureFormField(name, pageIndex, x, y, width, height);

// Add signature
pdf.Form.Add(signature);

pdf.SaveAs("signature.pdf");
Imports IronPdf
Imports IronSoftware.Forms

Private renderer As New ChromePdfRenderer()
Private pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>testing</h1>")

' Configure required parameters
Private name As String = "cert"
Private pageIndex As UInteger = 0
Private x As Double = 100
Private y As Double = 600
Private width As Double = 300
Private height As Double = 100

' Create signature
Private signature As New SignatureFormField(name, pageIndex, x, y, width, height)

' Add signature
pdf.Form.Add(signature)

pdf.SaveAs("signature.pdf")
$vbLabelText   $csharpLabel
Firma no firmada

Puedes leer más sobre IronPDF y los formularios que soporta en el artículo Cómo crear formularios PDF.

Chaknith Bin
Ingeniero de software
Chaknith trabaja en IronXL e IronBarcode. Tiene una gran experiencia en C# y .NET, ayudando a mejorar el software y a apoyar a los clientes. Sus conocimientos de las interacciones con los usuarios contribuyen a mejorar los productos, la documentación y la experiencia general.