PDF und ZUGFeRD-Rechnung remote signieren (PAdES) – SignPDFRemote

Thema
VB.NET
SDK-Mitglieder
LastError Licensekey
Codebeispiele
VB.NET, C#, VB6 / VBScript (COM)
Veröffentlicht

Kurz: Mit SignPDFRemote signiert das Aloaha ZUGFeRD SDK (ab Version 11.0.0.2) ein PDF – auch eine hybride ZUGFeRD-/Factur-X-Rechnung – über den CodeB Remote Signature Service – einen Bestandteil der CodeB EUID Wallet Software. Das SDK schickt das PDF per HTTPS an den Dienst und erhält es mit einer PAdES-Signatur (Level B-B bis B-LTA) zurück. Ein lokales Zertifikat, eine Smartcard oder ein Kartenleser werden nicht benötigt; die Signatur funktioniert auch unbeaufsichtigt im Stapel und aus VB6/VBA über COM.

Wann remote signieren?

  • Server und Batch-Jobs: Rechnungen werden automatisch erzeugt und signiert, ohne dass auf dem Server ein Zertifikat oder eine Karte installiert sein muss.
  • Zentrale Schlüsselverwaltung: Der Signaturschlüssel liegt beim Signaturdienst, nicht auf jedem Arbeitsplatz.
  • Langzeitprüfbarkeit: Mit Level B-LTA enthält das PDF Zeitstempel und Prüfdaten für die spätere Validierung.

CodeB EUID Wallet – jetzt auch für ZUGFeRD

Der CodeB Remote Signature Service ist Teil der CodeB EUID Wallet Software. Die EUID Wallet wird damit jetzt auch für ZUGFeRD genutzt: Das Aloaha ZUGFeRD SDK (SignPDFRemote), die ZUGFeRD GUI, der PDF Viewer und das Kommandozeilen-Tool zugcmd signieren E-Rechnungen direkt über den Signaturdienst der EUID Wallet – ohne Zertifikat oder Smartcard auf dem eigenen Rechner.

Voraussetzungen

  • Aloaha ZUGFeRD SDK ab Version 11.0.0.2 mit gültiger Lizenz.
  • Ein Benutzerkonto auf einem produktiven CodeB-Server (Remote Signature Service der CodeB EUID Wallet); für den Server-zu-Server-Aufruf muss im Mandanten die Anmeldung mit Benutzername und Passwort freigeschaltet sein.

Wichtig: https://phone.codeb.io ist nur der Testserver von CodeB. Er eignet sich zum Ausprobieren, darf aber nicht für produktive Umgebungen verwendet werden. Für den Produktivbetrieb benötigen Sie einen eigenen CodeB-Server bzw. Mandanten – sprechen Sie uns an: info@aloaha.com. In den Beispielen steht deshalb der Platzhalter https://IHR-CODEB-SERVER.

  • Internetzugang per HTTPS vom aufrufenden Rechner zum Signaturdienst.
  • Das PDF ist höchstens 10 MiB groß und nicht verschlüsselt.

VB.NET

Dim LicenseKey As String = "IHR-LIZENZSCHLUESSEL"
Dim alo As New Aloaha_ZUGFeRD.XML(Aloaha_ZUGFeRD.iXML.ZUGFeRDProfile.comfort, False, LicenseKey)

' Argumente: Eingabe-PDF, Ausgabe ("" = Eingabe ersetzen), Ihr CodeB-Server, Benutzer, Passwort,
' PAdES-Level, Grund, Ort, Kontakt, Überschreiben, Lizenz, tatsächliches Level (Rückgabe)
Dim level As String = ""
If alo.SignPDFRemote("C:\Rechnungen\RE-2026-0001_zugferd.pdf", "C:\Rechnungen\RE-2026-0001_signiert.pdf", _
                     "https://IHR-CODEB-SERVER", "benutzer@firma.de", "IHR-PASSWORT", "B-LTA", _
                     "Rechnungsfreigabe", "Musterstadt", "", True, LicenseKey, level) Then
    Console.WriteLine("Signiert, Level: " & level)
Else
    Console.WriteLine("Fehler: " & alo.LastError)
End If

C#

var alo = new Aloaha_ZUGFeRD.XML();
alo.Licensekey = licenseKey;
string level = "";
bool ok = alo.SignPDFRemote(@"C:\Rechnungen\RE-2026-0001_zugferd.pdf", @"C:\Rechnungen\RE-2026-0001_signiert.pdf",
                            "https://IHR-CODEB-SERVER", "benutzer@firma.de", "IHR-PASSWORT",
                            "B-T", "Rechnungsfreigabe", "Musterstadt", "", true, licenseKey, ref level);
Console.WriteLine(ok ? "Signiert, Level: " + level : "Fehler: " + alo.LastError);

VBA / VB6 (COM)

Dim alo As Object, level As String
Set alo = CreateObject("Aloaha_ZUGFeRD.XML")
alo.Licensekey = "IHR-LIZENZSCHLUESSEL"

If alo.SignPDFRemote("C:\Rechnungen\RE-2026-0001_zugferd.pdf", "C:\Rechnungen\RE-2026-0001_signiert.pdf", _
                     "https://IHR-CODEB-SERVER", "benutzer@firma.de", "IHR-PASSWORT", "B-LTA", _
                     "Rechnungsfreigabe", "Musterstadt", "", True, "", level) Then
    Debug.Print "Signiert, Level: " & level
Else
    Debug.Print "Fehler: " & alo.LastError
End If

Nach dem Update auf 11.0.0.2 die Typbibliothek neu registrieren, damit COM-Clients die neue Funktion sehen.

Ohne Dateien: SignPDFRemoteBytes

Für Web-Services und Datenbankanwendungen arbeitet SignPDFRemoteBytes direkt mit Bytes und gibt das signierte PDF zurück (oder Nothing im Fehlerfall):

Dim signiert() As Byte = alo.SignPDFRemoteBytes(pdfBytes, "https://IHR-CODEB-SERVER", "benutzer@firma.de", "IHR-PASSWORT", "B-T")
If signiert Is Nothing Then Console.WriteLine(alo.LastError)

Mit Mindeststufe: Klasse RemoteSigner (ab 11.0.0.3)

Für Server und Stapelverarbeitung gibt es ab Version 11.0.0.3 die eigene COM-Klasse Aloaha_ZUGFeRD.RemoteSigner. Sie signiert genauso wie SignPDFRemote (Firmensiegel über signDocBasic), bietet aber zusätzlich:

  • Mindeststufe (MinLevel, Standard B-B): Liefert der Dienst eine niedrigere Stufe, gilt die Signatur als fehlgeschlagen und es wird keine Datei geschrieben.
  • Begründung einer Herabstufung (LevelNote) sowie angeforderte und erzeugte Stufe (RequestedLevel, EffectiveLevel).
  • Wiederholung bei Ratenlimit (MaxRetries): Bei HTTP 429 wartet die Klasse die vom Dienst genannte Zeit ab und versucht es erneut.
  • Einstellungen aus der Registry (LoadSettings) für Server: HKLM\Software\Aloaha\ZUGFeRD\CSC mit BaseURL, User, PasswordProtected (mit ProtectPassword per Windows-DPAPI für den Rechner verschlüsselt), Level, MinLevel, Reason, Location, Contact, TimeoutSeconds, MaxRetries.
Dim rs As New Aloaha_ZUGFeRD.RemoteSigner
rs.LicenseKey = "IHR-LIZENZSCHLUESSEL"
rs.ServerURL = "https://IHR-CODEB-SERVER"
rs.UserName = "rechnungssiegel"
rs.Password = "IHR-PASSWORT"
rs.Level = "B-LTA"
rs.MinLevel = "B-T"          ' ohne Zeitstempel wird nicht signiert
rs.Reason = "Rechnungsfreigabe"
rs.MaxRetries = 2            ' Stapelverarbeitung: bei HTTP 429 abwarten und wiederholen

If rs.SealFile("C:\Rechnungen\RE-2026-0001_zugferd.pdf", "C:\Rechnungen\RE-2026-0001_signiert.pdf") Then
    Console.WriteLine("Signiert, Level: " & rs.EffectiveLevel & " " & rs.LevelNote)
Else
    Console.WriteLine("Fehler: " & rs.LastError)
End If

Aus VBA/VB6: Set rs = CreateObject("Aloaha_ZUGFeRD.RemoteSigner"), danach dieselben Eigenschaften. Die Klasse folgt keinen Weiterleitungen – Benutzername und Passwort gehen nur an die eingetragene Server-URL. Das Passwort wird nie ausgegeben.

Signatur-Level (PAdES)

LevelInhaltEinsatz
B-BBasis-Signatur (CMS mit Signaturzertifikat)einfache Integritätssicherung
B-Tzusätzlich Zeitstempel eines Zeitstempeldienstes (RFC 3161)nachweisbarer Signaturzeitpunkt
B-LTzusätzlich Prüfdaten (Zertifikate, OCSP) im PDFPrüfung ohne Online-Abfrage
B-LTA (Standard)zusätzlich Archiv-ZeitstempelLangzeitarchivierung

Kann der Dienst ein höheres Level gerade nicht erzeugen (z. B. weil der Zeitstempeldienst nicht erreichbar ist), signiert er mit dem nächstniedrigeren Level, statt abzubrechen. Welches Level tatsächlich entstanden ist, liefert der Parameter EffectiveLevel (z. B. AdES-B-T). Prüfen Sie es immer gegen Ihre Mindestanforderung – am einfachsten mit RemoteSigner.MinLevel, der GUI-Einstellung Mindeststufe oder zugcmd -minlevel.

ZUGFeRD-Rechnung signieren: Reihenfolge

  1. Rechnungsdaten erzeugen und als XML speichern (Schnellstart VB.NET).
  2. Das XML mit MergeXMLIntoPDF in das PDF/A-3 einbetten.
  3. Zuletzt mit SignPDFRemote signieren. Die Signatur wird als inkrementelle Aktualisierung angehängt; Inhalt und eingebettetes XML bleiben unverändert. Jede spätere Änderung am PDF macht die Signatur ungültig.
  4. Das signierte PDF in Ihren Tests mit einem PDF/A-Prüfprogramm (z. B. veraPDF) und einem E-Rechnungs-Validator prüfen. B-LT ergänzt ein /DSS-Verzeichnis, B-LTA einen Dokument-Zeitstempel – beides ist nach PAdES zulässig.

Fehlerbehandlung

Liefert die Funktion False (bzw. Nothing), steht der Grund in LastError. Das Passwort erscheint nie in Fehlermeldungen.

LastErrorBedeutung
HTTP 401 … invalid_credentialsBenutzername oder Passwort falsch, oder die Passwort-Anmeldung ist im Mandanten nicht freigeschaltet.
HTTP 400 … pdf_encrypted_unsupportedDas PDF ist verschlüsselt – vorher entschlüsseln.
HTTP 429 … (Retry-After: 30 s)Zu viele Aufrufe in kurzer Zeit (Limit: 30 pro Minute); nach der angegebenen Zeit erneut versuchen – RemoteSigner.MaxRetries erledigt das automatisch.
service delivered B-T, below the minimum B-LTNur bei RemoteSigner: Der Dienst konnte die Mindeststufe nicht erreichen (z. B. Prüfdaten nicht verfügbar); es wurde keine Datei geschrieben.
HTTP 301/302 … (redirect not followed)Die Server-URL leitet weiter. Aus Sicherheitsgründen folgt das SDK keinen Weiterleitungen – die endgültige https-Adresse eintragen.
PDF larger than 10 MiBGrenze des Signaturdienstes; das SDK prüft sie vor dem Senden.
ServerURL must start with https://Unverschlüsselte Verbindungen werden nicht unterstützt.
License ProblemKeine gültige Lizenz des SDK gesetzt.

Ohne Programmierung: ZUGFeRD GUI, PDF Viewer und zugcmd

Dieselbe Fernsignatur steckt ab Version 11.0.0.2 auch in der Aloaha ZUGFeRD GUI (Register PDF signieren) und im Aloaha ZUGFeRD PDF Viewer (Tools > PDF / ZUGFeRD-PDF signieren). Server-URL, Benutzer, Passwort und Signaturstufe tragen Sie einmal unter Signatur-Einstellungen ein; Verbindung testen prüft die Zugangsdaten mit einem Test-PDF; während der Signatur zeigt ein Fortschrittsfenster, dass der Dienst arbeitet. Ab Version 11.0.0.3 signiert auch das Kommandozeilen-Tool zugcmd per Fernsignatur (-remoteurl, -remoteuser, -remotepw, -level) – ideal für Stapelverarbeitung.

Rechtlicher Rahmen

Der CodeB Remote Signature Service erzeugt fortgeschrittene elektronische Signaturen (AdES) im Sinne der eIDAS-Verordnung, keine qualifizierten Signaturen (QES). Für E-Rechnungen ist eine elektronische Signatur in Deutschland nicht vorgeschrieben; sie sichert aber Echtheit und Unversehrtheit des Dokuments nachweisbar ab. Ob ein Prüfprogramm die Signatur als „vertrauenswürdig“ anzeigt, hängt davon ab, ob es dem ausstellenden Zertifikat vertraut.

Technischer Hintergrund

Die Funktion nutzt den Endpunkt signatures/signDocBasic der CSC-v2-Schnittstelle (Cloud Signature Consortium): ein HTTPS-POST mit Basic-Authentifizierung, das PDF im Request, das signierte PDF in der Antwort. Mehr zum Dienst: Remote-Signaturen bei CodeB.

Häufige Fragen

Wie signiere ich ein PDF per API ohne lokales Zertifikat?

Mit SignPDFRemote des Aloaha ZUGFeRD SDK: Die Funktion sendet das PDF per HTTPS an den CodeB Remote Signature Service und speichert das zurückgegebene, PAdES-signierte PDF. Ein Zertifikat oder eine Smartcard auf dem Rechner ist nicht nötig.

Bleibt eine ZUGFeRD-Rechnung nach dem Signieren gültig?

Ja, wenn zuerst das XML eingebettet und erst danach signiert wird. Die Signatur wird inkrementell angehängt, Inhalt und eingebettete Rechnungsdaten bleiben unverändert.

Welches Signatur-Level soll ich wählen?

Für die Archivierung B-LTA (Standard), sonst mindestens B-T mit Zeitstempel. Das tatsächlich erzeugte Level steht nach dem Aufruf im Parameter EffectiveLevel.

Was hat die CodeB EUID Wallet mit ZUGFeRD zu tun?

Der CodeB Remote Signature Service, über den SignPDFRemote signiert, ist Teil der CodeB EUID Wallet Software. Damit wird die EUID Wallet jetzt auch für ZUGFeRD genutzt: SDK, ZUGFeRD GUI, PDF Viewer und zugcmd signieren E-Rechnungen über ihren Signaturdienst.

Kann ich phone.codeb.io produktiv nutzen?

Nein. https://phone.codeb.io ist nur der Testserver von CodeB und nicht für produktive Umgebungen gedacht. Für den Produktivbetrieb tragen Sie die URL Ihres eigenen CodeB-Servers ein.

Ist das eine qualifizierte elektronische Signatur?

Nein. Der Dienst erzeugt fortgeschrittene elektronische Signaturen (AdES) nach eIDAS. Für E-Rechnungen ist in Deutschland keine Signatur vorgeschrieben.

Kann ich SignPDFRemote aus VBA oder VB6 aufrufen?

Ja. Die Funktion ist Teil der COM-Schnittstelle iXML und über CreateObject("Aloaha_ZUGFeRD.XML") verfügbar; nach dem Update die Typbibliothek neu registrieren.