Esta página puede contener texto traducido automáticamente.
Cómo firmar PDFs con tokens USB y dispositivos HSM en C# y VB.NET
Las autoridades de certificación de confianza ya no permiten exportar claves privadas para certificados de firma de documentos. En su lugar, las claves privadas deben almacenarse en hardware seguro como tokens USB, tarjetas inteligentes o HSM en la nube.
Puede usar biblioteca Docotic.Pdf para firmar documentos PDF en .NET usando dispositivos HSM. Este artículo describe integraciones con Azure Key Vault, AWS KMS y hardware compatible con PKCS#11.
Puede obtener la biblioteca y una clave de licencia gratuita con tiempo limitado en la página Descargar biblioteca PDF para C# .NET.

Prerrequisitos
Los ejemplos de código de este artículo usan certificados autofirmados para firmar documentos PDF. De forma predeterminada, los visores de PDF no confían en estas firmas. Los certificados autofirmados solo deben usarse para pruebas, no en entornos de producción. Para generar firmas PDF de confianza, use certificados de firma de documentos emitidos por autoridades de certificación de terceros.
Obtenga el certificado adecuado
Prefiera certificados de empresas incluidas en la Lista de confianza aprobada por Adobe (AATL). Adobe Acrobat confía de forma predeterminada en los certificados de esas empresas y no mostrará la advertencia "Certificate validity is unknown".
Para crear documentos compatibles con la UE (eIDAS), debe usar certificados cualificados emitidos por proveedores incluidos en las Listas de confianza de la Unión Europea (EUTL).
Aprenda a usar su certificado en .NET
Cuando solicite un certificado de firma de documentos, normalmente recibirá acceso a un dispositivo HSM. Puede ser un token USB físico o una solución HSM basada en la nube.
Luego debe aprender a firmar datos con este HSM. Esta suele ser la parte más complicada porque todos los proveedores criptográficos son diferentes. Debe seguir la documentación de su token USB o de la API en la nube.
Idealmente, necesita encontrar un SDK de .NET correspondiente. O, al menos, encontrar un SDK nativo y usarlo mediante interop en .NET.
Su objetivo es obtener código C# o VB.NET que pueda firmar cualquier secuencia de bytes usando su certificado.
API de PDF para firma externa
Una vez que pueda firmar cualquier secuencia de bytes con su dispositivo HSM, estará listo para firmar documentos PDF con Docotic.Pdf. Para ello, implemente la interfaz IPdfSigner y úsela para firmar.
Implemente la interfaz IPdfSigner
IPdfSigner declara dos miembros. La propiedad SignatureAlgorithm devuelve el algoritmo usado para firmar. Normalmente, usaría algoritmos RSA o ECDSA.
El método Sign es la parte clave del flujo de firma externa. Docotic.Pdf proporciona el resumen de los bytes de un documento PDF a este método. Debe firmar este resumen con su dispositivo HSM y devolver los bytes de una firma digital. Tenga en cuenta que aquí no debe devolver un objeto PKCS#7. Solo genere y devuelva la firma criptográfica.
Docotic.Pdf llama al método Sign dos veces por cada firma. La primera llamada calcula el espacio necesario para la firma. La segunda llamada firma realmente el documento.
Cree PdfSigningOptions para firma externa
Use el constructor PdfSigningOptions(IPdfSigner, X509Certificate2[]) para firmar documentos PDF con su implementación de IPdfSigner. Obtenga una cadena de certificados y proporciónela como segundo argumento. Se requiere al menos un certificado y el certificado de firma debe ir primero.
La última pieza del rompecabezas es la propiedad PdfSigningOptions.DigestAlgorithm. El valor de esta propiedad debe coincidir con IPdfSigner.SignatureAlgorithm y con la implementación de IPdfSigner.Sign.
Veamos cómo firmar PDFs con firmas externas en escenarios comunes.
Firmar documentos PDF usando el controlador PKCS#11 en C#
Si su token USB criptográfico o tarjeta inteligente incluye un controlador PKCS#11, entonces puede usar las bibliotecas Pkcs11Interop.X509Store o Pkcs11Interop en .NET. Pkcs11Interop es compatible con tarjetas inteligentes Atos CardOS, YubiKey PIV, SmartCard-HSM, SafeNet ProtectServer HSM y otros HSM.
El ejemplo de código Firmar documentos PDF utilizando los controladores PKCS#11 muestra cómo firmar documentos PDF con un token USB o una tarjeta inteligente. Deberá personalizar estas líneas:
string pkcsLibraryPath = @"C:\Program Files\SoftHSM2\lib\softhsm2-x64.dll";
ulong slotId = 1743347971;
string alias = "YOUR-ALIAS";
string certLabel = "YOUR-CERTIFICATE";
string pin = "YOUR-PIN";
var digestAlgorithm = PdfDigestAlgorithm.Sha512;
Nuestra configuración de ejemplo usa SoftHSM2 como emulador de un token USB. En aplicaciones reales, no necesita SoftHSM2. En su lugar, use el controlador que viene con el token USB.
Firmar documentos PDF usando Azure Key Vault
Microsoft Azure Key Vault almacena de forma segura certificados y claves. Deberá realizar las siguientes preparaciones:
- Cree una cuenta de Azure.
- Cree un usuario de Azure.
- Cree un Key Vault.
- Permita el acceso al Key Vault para el usuario de Azure seleccionado.
- Agregue un certificado de firma de documentos al Key Vault. Puede importar certificados de autoridades de certificación integradas.
Luego, use el paquete NuGet Azure.Security.KeyVault.Keys para firmar en .NET. Código de ejemplo en C# para firmar con una clave de Azure Key Vault:
var vaultUrl = new Uri("https://YOUR-VAULT.vault.azure.net/");
var credentials = new DefaultAzureCredential();
var keyClient = new KeyClient(vaultUrl, credentials);
KeyVaultKey key = keyClient.GetKey("YOUR-KEY");
var cryptoClient = new CryptographyClient(key.Id, credentials);
byte[] messageToSign = ..;
byte[] signature = cryptoClient.SignData(SignatureAlgorithm.RS512, messageToSign).Signature;
Una implementación relacionada de IPdfSigner podría verse así:
using AzureSignatureAlgorithm = SignatureAlgorithm;
class AzureSigner : IPdfSigner
{
private readonly CryptographyClient m_client;
private readonly AzureSignatureAlgorithm m_signingAlgorithm;
public AzureSigner(CryptographyClient client, AzureSignatureAlgorithm signingAlgorithm)
{
m_client = client;
m_signingAlgorithm = signingAlgorithm;
}
public PdfSignatureAlgorithm SignatureAlgorithm
{
get
{
if (m_signingAlgorithm == AzureSignatureAlgorithm.RS256 ||
m_signingAlgorithm == AzureSignatureAlgorithm.RS384 ||
m_signingAlgorithm == AzureSignatureAlgorithm.RS512)
return PdfSignatureAlgorithm.Rsa;
throw new NotSupportedException($"Unsupported {nameof(SignatureAlgorithm)} value: {m_signingAlgorithm}");
}
}
public PdfDigestAlgorithm DigestAlgorithm
{
get
{
if (m_signingAlgorithm == AzureSignatureAlgorithm.RS256)
return PdfDigestAlgorithm.Sha256;
if (m_signingAlgorithm == AzureSignatureAlgorithm.RS384)
return PdfDigestAlgorithm.Sha384;
if (m_signingAlgorithm == AzureSignatureAlgorithm.RS512)
return PdfDigestAlgorithm.Sha512;
throw new NotSupportedException($"Unsupported {nameof(SignatureAlgorithm)} value: {m_signingAlgorithm}");
}
}
public byte[] Sign(byte[] message)
{
return m_client.SignData(m_signingAlgorithm, message).Signature;
}
}
Por último, use esta clase AzureSigner para firmar documentos PDF:
CryptographyClient cryptoClient = ..;
using X509Certificate2 cert = ..;
var signer = new AzureSigner(cryptoClient, SignatureAlgorithm.RS512);
using var pdf = new PdfDocument();
PdfPage page = pdf.Pages[0];
PdfSignatureField field = page.AddSignatureField(50, 50, 200, 200);
var options = new PdfSigningOptions(signer, [cert])
{
DigestAlgorithm = signer.DigestAlgorithm,
Field = field,
};
pdf.SignAndSave(options, ..);
Explore el ejemplo completo de código Firmar documentos PDF con Azure Key Vault en GitHub.
Firmar documentos PDF usando AWS KMS
AWS Key Management Service (KMS) es otro almacenamiento seguro para claves criptográficas. La preparación sigue los mismos pasos que Azure Key Vault:
- Cree una cuenta de AWS.
- Cree un usuario IAM.
- Agregue una clave de firma.
- Permita el acceso a las claves para el usuario IAM seleccionado.
Para AWS, deberá usar el paquete NuGet AWSSDK.KeyManagementService en .NET. El código de ejemplo para la firma de PDF es muy similar al escenario de Azure:
using var pdf = new PdfDocument();
PdfPage page = pdf.Pages[0];
PdfSignatureField field = page.AddSignatureField(50, 50, 200, 200);
var signingAlgorithm = SigningAlgorithmSpec.RSASSA_PSS_SHA_512;
var signer = new AwsSigner("arn:aws:kms:YOUR-id", signingAlgorithm);
var options = new PdfSigningOptions(signer, [cert])
{
DigestAlgorithm = signer.DigestAlgorithm,
Field = field,
};
pdf.SignAndSave(options, ..);
class AwsSigner : IPdfSigner
{
private readonly string m_keyId;
private readonly SigningAlgorithmSpec m_signingAlgorithm;
public AwsSigner(string keyId, SigningAlgorithmSpec signingAlgorithm)
{
m_keyId = keyId;
m_signingAlgorithm = signingAlgorithm;
}
public PdfSignatureAlgorithm SignatureAlgorithm
{
get
{
if (m_signingAlgorithm == SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_256 ||
m_signingAlgorithm == SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_384 ||
m_signingAlgorithm == SigningAlgorithmSpec.RSASSA_PKCS1_V1_5_SHA_512)
return PdfSignatureAlgorithm.Rsa;
throw new NotSupportedException($"Unsupported {nameof(SigningAlgorithmSpec)} value: {m_signingAlgorithm}");
}
}
public PdfDigestAlgorithm DigestAlgorithm
{
get
{
string alg = m_signingAlgorithm.Value;
if (alg.EndsWith("256"))
return PdfDigestAlgorithm.Sha256;
if (alg.EndsWith("384"))
return PdfDigestAlgorithm.Sha384;
if (alg.EndsWith("512"))
return PdfDigestAlgorithm.Sha512;
throw new NotSupportedException($"Unsupported {nameof(SigningAlgorithmSpec)} value: {m_signingAlgorithm}");
}
}
public byte[] Sign(byte[] message)
{
using var kmsClient = new AmazonKeyManagementServiceClient();
using var stream = new MemoryStream(message);
var signRequest = new SignRequest()
{
SigningAlgorithm = m_signingAlgorithm,
KeyId = m_keyId,
MessageType = MessageType.RAW,
Message = stream,
};
SignResponse signResponse = kmsClient.SignAsync(signRequest).GetAwaiter().GetResult();
return signResponse.Signature.ToArray();
}
}
El ejemplo completo de código Firmar documentos PDF con AWS KMS también está disponible en GitHub.
Conclusión
Aproveche biblioteca Docotic.Pdf para firmar documentos PDF usando tokens USB, tarjetas inteligentes o HSM en la nube. Para ello, implemente la interfaz IPdfSigner en código C# o VB.NET.
Descargue y pruebe ejemplos de código para firmas digitales en PDF de GitHub. Consulte los artículos relacionados para obtener información adicional:
- Firmar documentos PDF en C# y VB.NET
- Verificar la firma PDF en C# y VB.NET
- Agregar información de Validación a Largo Plazo (PAdES-LTV) a las firmas de PDF en C#
Preguntas frecuentes
¿Cómo firmo un PDF usando un token USB o una tarjeta inteligente?
Use las bibliotecas Docotic.Pdf y Pkcs11Interop .NET para firmar PDFs con cualquiera de los dos, token o tarjeta inteligente. Consulte la sección Firmar documentos PDF usando el controlador PKCS#11 en C# para obtener más detalles.
¿Cómo uso SoftHSM con mi token USB o tarjeta inteligente?
SoftHSM simula un dispositivo HSM real. No necesita SoftHSM si tiene un token USB o una tarjeta inteligente. En su lugar, use el controlador PKCS#11 proporcionado con su dispositivo HSM.
¿Cómo firmo un documento PDF con una firma externa?
Consulte las secciones Firmar documentos PDF usando Azure Key Vault y Firmar documentos PDF usando AWS KMS. La firma externa de PDF con otros HSM en la nube sigue un proceso similar.
¿Cómo uso Azure Key Vault en .NET?
Use el paquete NuGet Azure.Security.KeyVault.Keys. Pruebe el ejemplo de código Firmar documentos PDF con Azure Key Vault de GitHub.