Diese Seite kann automatisch übersetzten Text enthalten.

Wie man PDFs mit USB-Tokens und HSM-Geräten in C# und VB.NET signiert

Vertrauenswürdige Zertifizierungsstellen erlauben das Exportieren privater Schlüssel für Zertifikate zum Signieren von Dokumenten nicht mehr. Stattdessen müssen private Schlüssel in sicherer Hardware wie USB-Tokens, Smartcards oder cloudbasierten HSMs gespeichert werden.

Sie können die Docotic.Pdf-Bibliothek verwenden, um PDF-Dokumente in .NET mit HSM-Geräten zu signieren. Dieser Artikel beschreibt Integrationen mit Azure Key Vault, AWS KMS und PKCS#11-kompatibler Hardware.

Sie können die Bibliothek und einen kostenlosen, zeitlich begrenzten Lizenzschlüssel auf der C# .NET-PDF-Bibliothek herunterladen-Seite erhalten.

Externes PDF-Signieren

Voraussetzungen

Die Codebeispiele in diesem Artikel verwenden selbstsignierte Zertifikate zum Signieren von PDF-Dokumenten. Standardmäßig vertrauen PDF-Viewer diesen Signaturen nicht. Selbstsignierte Zertifikate sollten nur zu Testzwecken und nicht in Produktionsumgebungen verwendet werden. Um vertrauenswürdige PDF-Signaturen zu erstellen, verwenden Sie Zertifikate zum Signieren von Dokumenten, die von Drittanbieter-Zertifizierungsstellen ausgestellt wurden.

Das richtige Zertifikat wählen

Bevorzugen Sie Zertifikate von Unternehmen, die in der Adobe Approved Trust List (AATL) aufgeführt sind. Adobe Acrobat vertraut Zertifikaten solcher Unternehmen standardmäßig und meldet die Warnung "Certificate validity is unknown" nicht.

Um EU-konforme (eIDAS) Dokumente zu erstellen, müssen Sie Qualified Certificates verwenden, die von Anbietern ausgestellt wurden, die in den European Union Trusted Lists (EUTL) aufgeführt sind.

Lernen Sie, wie Sie Ihr Zertifikat in .NET verwenden

Wenn Sie ein Zertifikat zum Signieren von Dokumenten bestellen, erhalten Sie in der Regel Zugriff auf ein HSM-Gerät. Das kann ein physischer USB-Token oder eine cloudbasierte HSM-Lösung sein.

Dann sollten Sie lernen, wie Sie Daten mit diesem HSM signieren. Das ist in der Regel der schwierigste Teil, weil sich alle Kryptografieanbieter unterscheiden. Sie sollten der Dokumentation für Ihren USB-Token oder Ihre Cloud-API folgen.

Idealerweise müssen Sie ein passendes .NET SDK finden. Oder zumindest ein natives SDK finden und es in .NET über Interop verwenden.

Ihr Ziel ist es, C#- oder VB.NET-Code zu erhalten, der beliebige Bytes mit Ihrem Zertifikat signieren kann.

PDF-API für externes Signieren

Sobald Sie mit Ihrem HSM-Gerät beliebige Bytes signieren können, sind Sie bereit, PDF-Dokumente mit Docotic.Pdf zu signieren. Implementieren Sie dazu die Schnittstelle IPdfSigner und verwenden Sie sie zum Signieren.

IPdfSigner-Schnittstelle implementieren

IPdfSigner deklariert zwei Mitglieder. Die Eigenschaft SignatureAlgorithm gibt den für die Signatur verwendeten Algorithmus zurück. Typischerweise verwenden Sie RSA- oder ECDSA-Algorithmen.

Die Methode Sign ist der Kern des externen Signierflusses. Docotic.Pdf übergibt den Digest der Bytes eines PDF-Dokuments an diese Methode. Sie sollten diesen Digest mit Ihrem HSM-Gerät signieren und die Bytes einer digitalen Signatur zurückgeben. Beachten Sie, dass Sie hier kein PKCS#7-Objekt zurückgeben dürfen. Generieren und geben Sie einfach die kryptografische Signatur zurück.

Docotic.Pdf ruft die Methode Sign für jede Signatur zweimal auf. Der erste Aufruf dient dazu, den benötigten Speicherplatz für die Signatur zu berechnen. Der zweite Aufruf dient dazu, das Dokument tatsächlich zu signieren.

PdfSigningOptions für externes Signieren erstellen

Verwenden Sie den Konstruktor PdfSigningOptions(IPdfSigner, X509Certificate2[]), um PDF-Dokumente mit Ihrer IPdfSigner-Implementierung zu signieren. Besorgen Sie sich eine Zertifikatskette und übergeben Sie sie als zweites Argument. Mindestens ein Zertifikat ist erforderlich, und das Signaturzertifikat sollte zuerst kommen.

Der letzte Baustein ist die Eigenschaft PdfSigningOptions.DigestAlgorithm. Der Wert dieser Eigenschaft muss zu IPdfSigner.SignatureAlgorithm und zur Implementierung von IPdfSigner.Sign passen.

Sehen wir uns an, wie man PDFs mit externen Signaturen in gängigen Szenarien signiert.

PDF-Dokumente mit PKCS#11-Treiber in C# signieren

Wenn Ihr kryptografischer USB-Token oder Ihre Smartcard mit einem PKCS#11-Treiber geliefert wird, können Sie die .NET-Bibliotheken Pkcs11Interop.X509Store oder Pkcs11Interop verwenden. Pkcs11Interop ist mit Atos-CardOS-Smartcards, YubiKey PIV, SmartCard-HSM, SafeNet ProtectServer HSM und anderen HSMs kompatibel.

Das Codebeispiel Signieren Sie PDF-Dokumente mit PKCS#11-Treibern zeigt, wie man PDF-Dokumente mit einem USB-Token oder einer Smartcard signiert. Sie müssen diese Zeilen anpassen:

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;

Unsere Beispielkonfiguration verwendet SoftHSM2 als Emulator eines USB-Tokens. In realen Anwendungen benötigen Sie SoftHSM2 nicht. Verwenden Sie stattdessen den Treiber, der mit dem USB-Token geliefert wird.

PDF-Dokumente mit Azure Key Vault signieren

Microsoft Azure Key Vault speichert Zertifikate und Schlüssel sicher. Sie müssen die folgenden Vorbereitungen treffen:

  1. Erstellen Sie ein Azure-Konto.
  2. Erstellen Sie einen Azure-Benutzer.
  3. Erstellen Sie einen Key Vault.
  4. Erlauben Sie dem ausgewählten Azure-Benutzer den Zugriff auf den Key Vault.
  5. Fügen Sie dem Key Vault ein Zertifikat zum Signieren von Dokumenten hinzu. Sie können Zertifikate von integrierten Zertifizierungsstellen importieren.

Verwenden Sie dann das NuGet-Paket Azure.Security.KeyVault.Keys zum Signieren in .NET. Beispielcode in C# zum Signieren mit einem Schlüssel aus 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;

Eine zugehörige IPdfSigner-Implementierung könnte so aussehen:

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;
    }
}

Verwenden Sie schließlich diese AzureSigner-Klasse, um PDF-Dokumente zu signieren:

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, ..);

Sehen Sie sich das vollständige Codebeispiel Signieren Sie PDF-Dokumente mit Azure Key Vault auf GitHub an.

PDF-Dokumente mit AWS KMS signieren

AWS Key Management Service (KMS) ist ein weiterer sicherer Speicher für kryptografische Schlüssel. Die Vorbereitung erfolgt nach denselben Schritten wie bei Azure Key Vault:

  1. Erstellen Sie ein AWS-Konto.
  2. Erstellen Sie einen IAM-Benutzer.
  3. Fügen Sie einen Signaturschlüssel hinzu.
  4. Erlauben Sie dem ausgewählten IAM-Benutzer den Zugriff auf die Schlüssel.

Für AWS müssen Sie in .NET das NuGet-Paket AWSSDK.KeyManagementService verwenden. Der Beispielcode für die PDF-Signierung ist dem Azure-Szenario sehr ähnlich:

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();
    }
}

Das vollständige Codebeispiel Signieren Sie PDF-Dokumente mit AWS KMS ist ebenfalls auf GitHub verfügbar.

Abschluss

Nutzen Sie die Docotic.Pdf-Bibliothek zum Signieren von PDF-Dokumenten mit USB-Tokens, Smartcards oder cloudbasierten HSMs. Implementieren Sie dazu die Schnittstelle IPdfSigner in C#- oder VB.NET-Code.

Laden Sie Codebeispiele für digitale Signaturen in PDF von GitHub herunter und probieren Sie sie aus. Prüfen Sie verwandte Artikel für zusätzliche Informationen:

Häufig gestellte Fragen

Wie signiere ich ein PDF mit einem USB-Token oder einer Smartcard?

Verwenden Sie die .NET-Bibliotheken Docotic.Pdf und Pkcs11Interop, um PDFs entweder mit einem Token oder mit einer Smartcard zu signieren. Weitere Details finden Sie im Abschnitt PDF-Dokumente mit PKCS#11-Treiber in C# signieren.

Wie verwende ich SoftHSM mit meinem USB-Token oder meiner Smartcard?

SoftHSM simuliert ein echtes HSM-Gerät. Sie benötigen SoftHSM nicht, wenn Sie einen USB-Token oder eine Smartcard haben. Verwenden Sie stattdessen den PKCS#11-Treiber, der mit Ihrem HSM-Gerät geliefert wird.

Wie signiere ich ein PDF-Dokument mit einer externen Signatur?

Sehen Sie sich die Abschnitte PDF-Dokumente mit Azure Key Vault signieren und PDF-Dokumente mit AWS KMS signieren an. Externes PDF-Signieren mit anderen cloudbasierten HSMs folgt einem ähnlichen Ablauf.

Wie verwende ich Azure Key Vault in .NET?

Verwenden Sie das NuGet-Paket Azure.Security.KeyVault.Keys. Probieren Sie das Codebeispiel Signieren Sie PDF-Dokumente mit Azure Key Vault von GitHub aus.