Firma HSM para TicketBAI, eIDAS y Crea y Crece: PAdES y XAdES con IronPDF en C

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronPDF permite la firma segura de PDF mediante Módulos de Seguridad de Hardware (HSM) a través de la API PKCS#11, donde las claves privadas nunca salen del dispositivo físico. En España, la firma con HSM es el mecanismo de referencia para tres casos de uso normativos críticos:

  1. TicketBAI en el País Vasco: las empresas en Bizkaia, Gipuzkoa y Araba que generan facturas de alto volumen usan HSMs con certificados FNMT o IZENPE (la autoridad de certificación del País Vasco) para firmar registros XAdES de forma masiva, cumpliendo las especificaciones forales sin exponer las claves privadas.
  2. Firma cualificada eIDAS (QES): para documentos que requieren valor probatorio legal bajo eIDAS, la firma mediante HSM con un certificado cualificado emitido por la FNMT proporciona el nivel más alto de firma electrónica reconocida en toda la Unión Europea.
  3. Crea y Crece y facturas B2B: la ley Crea y Crece exige firmas PAdES en facturas Facturae para el intercambio B2B. Los ISVs que generan decenas de miles de facturas por hora utilizan HSMs para gestionar las claves de firma sin riesgo de exposición.

Inicio rápido: Firmar un PDF con HSM en C#

  1. Instala IronPDF a través de NuGet: Install-Package IronPdf
  2. Configure su dispositivo HSM (o utilice SoftHSM para realizar pruebas)
  3. Crea un UsbPkcs11HsmSigner con tus credenciales HSM:
    1. Instala IronPDF con el Administrador de Paquetes NuGet

      PM > Install-Package IronPdf
    2. Copie y ejecute este fragmento de código.

      var hsmSigner = new UsbPkcs11HsmSigner(libraryPath, pin, tokenLabel, keyLabel);
    3. Despliegue para probar en su entorno real

      Comienza a usar IronPDF en tu proyecto hoy mismo con una prueba gratuita

      arrow pointer
  4. Genere su PDF y fírmelo:
    var pdf = renderer.RenderHtmlAsPdf("<h1>Document</h1>");
    pdf.SignAndSave("signed.pdf", hsmSigner);
    var pdf = renderer.RenderHtmlAsPdf("<h1>Document</h1>");
    pdf.SignAndSave("signed.pdf", hsmSigner);
    Dim pdf = renderer.RenderHtmlAsPdf("<h1>Document</h1>")
    pdf.SignAndSave("signed.pdf", hsmSigner)
    $vbLabelText   $csharpLabel
  5. Verifique la firma en su visor de PDF

Añadir una firma a un documento PDF es un requisito habitual en aplicaciones de facturación y gestión documental. Sin embargo, las aplicaciones de misión crítica —como los sistemas de facturación certificados para TicketBAI o VeriFactu— requieren mayor seguridad. Una firma normal con un fichero .pfx carga la clave en la memoria: si el servidor se ve comprometido, la clave puede ser robada y usada para generar facturas fraudulentas.

Un HSM mantiene la clave privada generada dentro del dispositivo y nunca permite que salga. La aplicación proporciona un PIN, el HSM lleva a cabo la operación de firma internamente y retorna el documento firmado. La clave nunca sale del dispositivo.

Firma HSM con certificados FNMT e IZENPE para TicketBAI

Para el caso de uso de TicketBAI en el País Vasco, es importante entender que cada diputación foral tiene especificaciones propias:

  • Bizkaia (portal bizkaia.eus, programa BATUZ): acepta firmas XAdES con certificados FNMT o IZENPE.
  • Gipuzkoa (gipuzkoa.eus): especificaciones XAdES ligeramente distintas en los campos obligatorios del sobre de firma.
  • Araba (araba.eus): comparte la arquitectura base de TicketBAI pero con su propio endpoint de validación.

IronPDF no es por sí mismo un sistema de facturación certificado para TicketBAI: es el componente que genera el PDF firmado que se incorpora al registro TicketBAI dentro de su sistema de facturación certificado. La firma con HSM garantiza que las claves de firma de su empresa permanecen seguras aunque el servidor de aplicación se vea comprometido.

¿Cómo firmar archivos PDF con un HSM?

La firma con HSM requiere un dispositivo físico (token USB) con el que interactúa la aplicación. IronPDF es compatible con estos dispositivos porque tanto la biblioteca como los HSMs estándar utilizan PKCS#11 como API común.

Para entornos de producción, utilice su HSM real. Para pruebas, puede usar SoftHSM.

Para ejecutar la simulación, primero instale SoftHSM, OpenSSL y OpenSC para generar la clave y el token necesarios.

¿Qué aspecto tiene el código de firma HSM?

:path=/static-assets/pdf/content-code-examples/how-to/signing-with-hsm.cs
using IronPdf;
using IronPdf.Signing;
using IronSoftware.Pdfium.Signing;
using System.Drawing;

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

// Define Paths and Credentials
string softhsmLibraryPath = @"D:\SoftHSM2\lib\softhsm2-x64.dll";
// These MUST match what you created
string hsmTokenLabel = "MyTestToken";
string hsmPin = "123456";
string hsmKeyLabel = "my-key"; // The label for the key *inside* the token

// Create the HsmSigner object.
UsbPkcs11HsmSigner hsmSigner = new UsbPkcs11HsmSigner(
    softhsmLibraryPath,
    hsmPin,
    hsmTokenLabel,
    hsmKeyLabel
);

// Create the Signature Image
string signatureImagePath = "IronSoftware.png";
PdfSignatureImage sigImage = new PdfSignatureImage(signatureImagePath, 0, new Rectangle(50, 50, 150, 150));

// Sign PDF with HSM
pdf.SignAndSave("signedWithHSM.pdf", hsmSigner);
Imports IronPdf
Imports IronPdf.Signing
Imports IronSoftware.Pdfium.Signing
Imports System.Drawing

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

' Define Paths and Credentials
Dim softhsmLibraryPath As String = "D:\SoftHSM2\lib\softhsm2-x64.dll"
' These MUST match what you created
Dim hsmTokenLabel As String = "MyTestToken"
Dim hsmPin As String = "123456"
Dim hsmKeyLabel As String = "my-key" ' The label for the key *inside* the token

' Create the HsmSigner object.
Dim hsmSigner As New UsbPkcs11HsmSigner(softhsmLibraryPath, hsmPin, hsmTokenLabel, hsmKeyLabel)

' Create the Signature Image
Dim signatureImagePath As String = "IronSoftware.png"
Dim sigImage As New PdfSignatureImage(signatureImagePath, 0, New Rectangle(50, 50, 150, 150))

' Sign PDF with HSM
pdf.SignAndSave("signedWithHSM.pdf", hsmSigner)
$vbLabelText   $csharpLabel

El UsbPkcs11HsmSigner acepta dos parámetros opcionales: digestAlgorithm y signingAlgorithm. Por defecto, están configurados como SHA256 y RSA.

Configuración avanzada para PAdES y múltiples firmas

Para firmas PAdES requeridas por Crea y Crece en facturas B2B o para firmas eIDAS con valor probatorio cualificado:

// Configure with custom algorithms
var customHsmSigner = new UsbPkcs11HsmSigner(
    hsmLibraryPath,
    hsmPin,
    hsmTokenLabel,
    hsmKeyLabel,
    digestAlgorithm: IronPdf.Signing.DigestAlgorithm.SHA512,
    signingAlgorithm: IronPdf.Signing.SigningAlgorithm.RSA
);

// Apply signature with custom location and reason
var signatureOptions = new SignatureOptions
{
    SignerName = "Corporate Signing Authority",
    Location = "Company Headquarters",
    Reason = "Contract Approval"
};

// Load existing PDF for signing
var existingPdf = PdfDocument.FromFile("contract.pdf");
existingPdf.SignAndSave("contract-signed.pdf", customHsmSigner, signatureOptions);
// Configure with custom algorithms
var customHsmSigner = new UsbPkcs11HsmSigner(
    hsmLibraryPath,
    hsmPin,
    hsmTokenLabel,
    hsmKeyLabel,
    digestAlgorithm: IronPdf.Signing.DigestAlgorithm.SHA512,
    signingAlgorithm: IronPdf.Signing.SigningAlgorithm.RSA
);

// Apply signature with custom location and reason
var signatureOptions = new SignatureOptions
{
    SignerName = "Corporate Signing Authority",
    Location = "Company Headquarters",
    Reason = "Contract Approval"
};

// Load existing PDF for signing
var existingPdf = PdfDocument.FromFile("contract.pdf");
existingPdf.SignAndSave("contract-signed.pdf", customHsmSigner, signatureOptions);
Imports IronPdf

' Configure with custom algorithms
Dim customHsmSigner As New UsbPkcs11HsmSigner(
    hsmLibraryPath,
    hsmPin,
    hsmTokenLabel,
    hsmKeyLabel,
    digestAlgorithm:=IronPdf.Signing.DigestAlgorithm.SHA512,
    signingAlgorithm:=IronPdf.Signing.SigningAlgorithm.RSA
)

' Apply signature with custom location and reason
Dim signatureOptions As New SignatureOptions With {
    .SignerName = "Corporate Signing Authority",
    .Location = "Company Headquarters",
    .Reason = "Contract Approval"
}

' Load existing PDF for signing
Dim existingPdf As PdfDocument = PdfDocument.FromFile("contract.pdf")
existingPdf.SignAndSave("contract-signed.pdf", customHsmSigner, signatureOptions)
$vbLabelText   $csharpLabel

¿Cuáles son los problemas comunes de configuración de HSM?

Si se encuentra con el error mostrado a continuación, siga estos pasos para depurar. Para ayuda adicional, consulte nuestra guía de solución de problemas de firmas digitales.

El error CKR_GENERAL_ERROR ocurre comúnmente cuando el programa no puede encontrar el fichero de configuración de SoftHSM o cuando la aplicación .NET se ejecuta como proceso de 32 bits mientras que la biblioteca de SoftHSM es de 64 bits.

Error de inicialización de PKCS#11 HSM que muestra CHR_GENERAL_ERROR en la salida de consola con seguimiento de pila completo

Cambiar la plataforma de destino

Su aplicación C# debe ejecutarse como proceso de 64 bits para coincidir con la biblioteca de 64 bits de SoftHSM (CHOOSE_x64). En las propiedades del proyecto en Visual Studio, cambie el objetivo de la Plataforma de 'Any CPU' o 'x86' a x64.

Configuración de compilación de Visual Studio que muestra el objetivo de plataforma establecido en arquitectura x64 con símbolos de compilación condicional

Configuración de la variable de entorno

Indique a la biblioteca dónde buscar estableciendo una variable de entorno. Cree una nueva variable llamada SOFTHSM2_CONF con la ruta completa a su fichero de configuración (por ejemplo, D:\SoftHSM2\etc\softhsm2.conf). Reinicie Visual Studio después de realizar los cambios. softhsm2-x64.dll x64 SOFTHSM2_CONF

Diálogo de variables de sistema de Windows con la variable de entorno SOFTISM2_CONF resaltada mostrando la ruta de configuración de HSM

Para verificar que la variable está configurada:

Console.WriteLine($"Verifying variable: {Environment.GetEnvironmentVariable("SOFTHSM2_CONF")}");
Console.WriteLine($"Verifying variable: {Environment.GetEnvironmentVariable("SOFTHSM2_CONF")}");
Console.WriteLine($"Verifying variable: {Environment.GetEnvironmentVariable(""SOFTHSM2_CONF"")}")
$vbLabelText   $csharpLabel

Si la salida aparece en blanco, configure la variable, reinicie Visual Studio y vuelva a intentarlo.

Prácticas recomendadas para implantación HSM en producción

Al desplegar PDFs firmados con HSM para TicketBAI, Crea y Crece o eIDAS en entornos de producción:

  1. Registro de auditoría: implemente un registro exhaustivo de todas las operaciones HSM para el seguimiento de acceso y la conformidad con la LOPDGDD y los requisitos de auditoría de la AEAT
  2. Gestión de certificados FNMT/IZENPE: actualice y rote periódicamente los certificados conforme a las políticas de las autoridades de certificación. Los certificados FNMT tienen validez limitada y deben renovarse antes de su caducidad para evitar interrupciones en la facturación
  3. Procedimientos de copia de seguridad: establezca procedimientos adecuados de recuperación para configuraciones HSM. Una clave perdida sin respaldo impide firmar facturas, lo que puede paralizar la operación de facturación bajo VeriFactu o TicketBAI
  4. Optimización del rendimiento: supervise el rendimiento de firma e implemente estrategias de caché para certificados de acceso frecuente en sistemas de alta facturación como los requeridos por SII (Suministro Inmediato de Información) ante la AEAT

Estas prácticas complementan el flujo de firma de PDF y garantizan que su infraestructura de seguridad documental permanezca robusta ante inspecciones fiscales.

Preguntas Frecuentes

¿Cómo configuro IronPDF para firmar PDFs de TicketBAI con un HSM IZENPE en Bizkaia, Gipuzkoa o Araba?

Cada hacienda foral tiene especificaciones técnicas propias: Bizkaia usa el sistema BATUZ con envíos a bizkaia.eus, Gipuzkoa a gipuzkoa.eus y Araba a araba.eus. En todos los casos, cree un UsbPkcs11HsmSigner con la ruta a la biblioteca PKCS#11 del HSM IZENPE, el PIN del token y las etiquetas del certificado de firma TicketBAI. IronPDF aplica la firma XAdES requerida sin exponer la clave privada.

¿Qué diferencia hay entre firma eIDAS QES y firma TicketBAI con HSM en IronPDF?

La firma eIDAS QES (Firma Electrónica Cualificada) requiere un certificado cualificado emitido por un prestador de servicios de confianza cualificado (QTSP) de la lista de confianza eIDAS de la UE, como FNMT o IZENPE. TicketBAI acepta firmas XAdES con certificados reconocidos por las haciendas forales vascas, que pueden o no ser QES. IronPDF soporta ambos escenarios mediante UsbPkcs11HsmSigner: la diferencia está en el tipo de certificado cargado en el HSM, no en el código C#.

¿Cómo implemento firma PAdES para Crea y Crece (B2B) con HSM en C#?

La ley Crea y Crece exige firmas electrónicas reconocidas en facturas B2B. Configure UsbPkcs11HsmSigner con el certificado FNMT de persona jurídica y use SignAndSave con el perfil de firma PAdES-B. Para facturas Facturae 3.2.2, el PDF/A-3b resultante debe contener tanto la firma PAdES en el PDF como el XML Facturae firmado con XAdES. IronPDF gestiona la parte PAdES del PDF; el XML Facturae se firma con herramientas externas antes de embeberse.

¿Puedo usar el mismo HSM para firmar PDFs de TicketBAI y facturas FACe con IronPDF?

Sí. Un HSM puede contener múltiples certificados: uno IZENPE para TicketBAI en el País Vasco y uno FNMT para facturas enviadas a FACe (portal B2G de la Administración General del Estado). IronPDF permite instanciar un UsbPkcs11HsmSigner diferente por cada etiqueta de clave, usando el mismo dispositivo físico pero seleccionando el certificado adecuado según el portal de destino.

¿Cómo gestiono el ciclo de vida del certificado HSM para producción en un ISV de facturación española?

Los certificados FNMT tienen validez de 2 años y los de IZENPE de 2-3 años según el tipo. Implemente un mecanismo de notificación de renovación con al menos 60 días de antelación. En producción, use HSMs en red (Luna Network HSM, Thales nShield) en lugar de tokens USB para garantizar alta disponibilidad. IronPDF soporta cualquier dispositivo con driver PKCS#11 compatible: el patrón UsbPkcs11HsmSigner funciona igual para HSMs físicos locales, tokens USB y HSMs en red.

Curtis Chau
Escritor Técnico

Curtis Chau tiene una licenciatura en Ciencias de la Computación (Carleton University) y se especializa en el desarrollo front-end con experiencia en Node.js, TypeScript, JavaScript y React. Apasionado por crear interfaces de usuario intuitivas y estéticamente agradables, disfruta trabajando con frameworks modernos y creando manuales bien ...

Leer más
¿Listo para empezar?
Nuget Descargas 18,926,724 | Versión: 2026.5 just released
Still Scrolling Icon

¿Aún desplazándote?

¿Quieres una prueba rápida? PM > Install-Package IronPdf
ejecutar una muestra Mira cómo tu HTML se convierte en PDF.