Zum Inhalt springen
getnextpdf.com

Enterprise Edition

Signieren mit Hardware-Sicherheitsmodul (PKCS#11)

NextPDF Enterprise signiert ein PDF mit einem Schlüssel, der in einem Hardware-Sicherheitsmodul (HSM) gehalten wird. Sie richten den Signer auf einen PKCS#11-Token aus — eine Smartcard, einen Universal-Serial-Bus-(USB-)Token oder ein netzgebundenes HSM —, und die Signieroperation läuft auf dem Gerät. Der private Schlüssel verlässt die Token-Grenze nie. Diese Seite ist verhaltensorientiert: Sie legt dar, was der Signer tut, was Sie bereitstellen und wo die Schlüsselverwahrung aufhört, NextPDFs Verantwortung zu sein.

Der HSM-Signer wird über den Core-Signer-Vertrag aufgelöst, sodass Ihre Anwendung vom Vertrag abhängt, nicht vom konkreten Enterprise-Typ. Er erweitert denselben Cryptographic-Message-Syntax-(CMS-)Signierpfad, den Core verwendet, nur dass die kryptografische Operation an den Token delegiert wird.

Die Voraussetzungen sind in der Front Matter angegeben und unter Voraussetzungen wiederholt, sodass Sie nicht mitten in der Aufgabe überrascht werden.

Diese Fähigkeit wird in NextPDF Enterprise (nextpdf/enterprise) ausgeliefert und aktiviert sich mit einem Lizenzumschlag der Enterprise-Stufe. Eine Bereitstellung ohne diese Berechtigung lädt die Klassen der Fähigkeit nicht. Editionen vergleichen und eine Lizenz erwerben.

NextPDF Core liefert einen Software-CMS-Signer, der den Schlüssel prozessintern hält oder einen über den Core-Signierstrategie-Vertrag akzeptiert; NextPDF Pro ergänzt Remote- und Cloud-Key-Management-Service-(KMS-)Signierstrategien. Hardware-Schlüsselverwahrung über PKCS#11 ist eine Enterprise-Fähigkeit und wird von Core oder Pro nicht bereitgestellt.

Ein PKCS#11-Token legt kryptografische Objekte — Zertifikate und private Schlüssel — hinter einer Vendor-Shared-Library offen. Der Enterprise-Signer adaptiert diese Library:

  1. Er öffnet die Shared Library des Tokens einmal pro Prozess und cached das Modul-Handle, weil PKCS#11 verlangt, dass das Modul genau einmal pro Prozess initialisiert wird.
  2. Er öffnet eine Sitzung auf dem konfigurierten Slot und meldet sich mit dem bereitgestellten PIN an. Der Login authentifiziert den Benutzer vor jeder Privatschlüsseloperation, gemäß PKCS#11 v3.1 §5.6.8.
  3. Er lokalisiert das Signaturzertifikat auf dem Token per Label, liest das Zertifikat in Distinguished-Encoding-Rules-(DER-)Form und erkennt den Public-Key-Algorithmus.
  4. Zum Signierzeitpunkt lokalisiert er den privaten Schlüssel per Label — das sich auf manchen Token vom Zertifikatslabel unterscheiden kann — und bittet den Token, die Signatur zu berechnen. Die zu signierenden Daten werden übergeben; der Schlüssel bleibt auf dem Gerät.

Der Signer unterstützt RSA mit PKCS#1-v1.5-Padding (SHA-256, SHA-384, SHA-512), RSA mit Probabilistic-Signature-Scheme-(PSS-)Padding, bei dem die Salt-Länge der Digest-Länge entspricht, und Elliptic Curve Digital Signature Algorithm (ECDSA) mit SHA-256, SHA-384 und SHA-512. Die ECDSA-Kurve und der Digest werden konventionell gepaart — P-256 mit SHA-256, P-384 mit SHA-384, P-521 mit SHA-512 — gemäß der empfohlenen Paarung in RFC 5480. Ein Token gibt eine ECDSA-Signatur als rohe Verkettung der zwei Ganzzahlen zurück; der Signer konvertiert sie in die DER-kodierte Form, die PDF und OpenSSL erwarten.

Für die Signaturerzeugung sind ein RSA-Schlüssel von mindestens 2048 Bit und eine ECDSA-Kurvenordnung von mindestens 224 Bit die akzeptablen Mindestwerte gemäß NIST SP 800-131A Rev.2 §3. Stellen Sie Ihren Token-Schlüssel auf oder über diesen Größen bereit.

Ein alternativer OpenSSL-Engine-Pfad existiert für engine-gestützte Token. Auf OpenSSL 3.x legt die PHP-OpenSSL-Erweiterung die Engine-Application-Programming-Interface (API) nicht offen, sodass die Engine-Klasse veraltet ist; die unterstützte engine-gestützte Route führt das OpenSSL-Kommandozeilenbinary aus. Bevorzugen Sie den direkten PKCS#11-Pfad, wo Ihr Token eine PKCS#11-Library besitzt.

Die tragende Entscheidung ist, dass der private Schlüssel den Token nie verlässt. Daher delegiert der Signer die kryptografische Operation an das Gerät und bewegt nur die zu signierenden Daten über die PKCS#11-Naht. Er liest oder rekonstruiert nie Schlüsselmaterial im PHP-Speicher. Er wird über den Core-HsmSignerInterface-Vertrag aufgelöst statt über einen konkreten Enterprise-Typ, sodass der Signiercode identisch ist, gleich ob der Schlüssel in Software, einem Cloud-KMS oder einem Hardware-Token lebt. Er cached das Modul-Handle einmal pro Prozess, weil PKCS#11 jedes Modul genau einmal pro Prozess initialisiert, und konvertiert dann die rohe ECDSA-Ausgabe des Tokens in DER, sodass Validatoren die erwartete Kodierung sehen. Verwahrung, nicht Bequemlichkeit, prägt die Form: Die Vertrauensgrenze bleibt am Geräterand.

Design-Hintergrund: HSM-gestütztes Signieren.

Bevor Sie mit einem HSM signieren, bestätigen Sie jeden Punkt:

  1. Installieren Sie NextPDF Core und das Enterprise-Paket: composer require nextpdf/core:^3 und composer require nextpdf/enterprise.
  2. Halten Sie eine aktive NextPDF Enterprise-Lizenz; lösen Sie das Paket gegen Ihre Lizenzanmeldedaten auf Private Packagist auf.
  3. Installieren Sie die PKCS#11-Shared-Library des Token-Herstellers auf dem Host (zum Beispiel eine .so unter Linux oder eine .dll unter Windows) und notieren Sie ihren absoluten Pfad, die Slot-Nummer und die Objekt-Labels.
  4. Laden Sie die ext-pkcs11-PHP-Erweiterung. Sie ist nicht im Standard-PHP gebündelt und muss separat installiert werden. Der Signer-Konstruktor löst einen typisierten Operationsfehler aus, wenn die Erweiterung fehlt.

Stellen Sie dem Signer diese Eingaben bereit:

  • Library-Pfad — der absolute Pfad zur Vendor-PKCS#11-Shared-Library.
  • Slot-Bezeichner — die Token-Slot-Nummer, typischerweise 0.
  • PIN — der Token-PIN. Behandeln Sie ihn als Geheimnis: Stellen Sie ihn aus Ihrem Secret Manager bereit, niemals aus dem Quellcode oder Protokollen. Der Signer markiert den PIN-Parameter als sensibel, sodass er von Stack Traces und Serialisierung ausgenommen ist.
  • Zertifikatslabel — das Label des Zertifikatsobjekts auf dem Token.
  • Schlüssellabel — das Label des Privatschlüsselobjekts, wenn es sich vom Zertifikatslabel unterscheidet.
  • Kette — optionale Zwischenzertifikate in DER-Form, wenn der Token sie nicht hält.

Prüfen Sie die Token-Verfügbarkeit, bevor Sie den Signer konstruieren. Die Konstruktion liest das Zertifikat vom Token, sodass ein falsch konfigurierter Slot oder ein falsches Label schnell mit einem typisierten Fehler scheitert, statt zur Signierzeit.

  1. Bestätigen Sie, dass die Laufzeitumgebung PKCS#11 unterstützt, indem Sie die Verfügbarkeit der Erweiterung prüfen. Konstruieren Sie den Signer nicht, wenn die Erweiterung fehlt.
  2. Lesen Sie den PIN aus Ihrem Secret Manager in eine Variable, die niemals protokolliert wird.
  3. Konstruieren Sie den HSM-Signer mit dem Library-Pfad, dem Slot, dem PIN und den Labels. Die Konstruktion meldet sich an und liest das Zertifikat.
  4. Übergeben Sie den Signer über HsmSignerInterface an den Core-Signier-Orchestrator. Der Orchestrator berechnet den Byte-Bereich, baut die signierten CMS-Attribute, übergibt die Daten an den Token und setzt das signierte PDF zusammen.
  5. Fangen Sie den spezifischsten Fehler ab, protokollieren Sie eine strukturelle Meldung ohne den PIN und werfen Sie erneut.
examples/contracts/hsm-signer-availability.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\HsmSignerInterface;
/**
* Build a hardware-token signer only when the runtime supports it.
*
* The concrete PKCS#11 signer is resolved through the Core contract so the
* caller depends on the interface, not the Enterprise implementation type.
* The PIN arrives from a secret resolver; it is never written to source.
*
* @param callable(): bool $pkcs11Available Reports ext-pkcs11 availability.
* @param callable(): HsmSignerInterface $signerFactory Builds the configured token signer.
*
* @throws \RuntimeException When the PKCS#11 extension is not loaded.
*
* @return HsmSignerInterface The token signer, ready for the Core orchestrator.
*/
function resolveHsmSigner(callable $pkcs11Available, callable $signerFactory): HsmSignerInterface
{
if ($pkcs11Available() !== true) {
throw new \RuntimeException(
'PKCS#11 signing requires the ext-pkcs11 extension; install it before signing.',
);
}
return $signerFactory();
}

Die Produktionsverdrahtung — die exakte Konstruktor-Argumentliste und die typisierten Ausnahmetypen — ist in der HSM-Deep-Reference dokumentiert.

examples/contracts/hsm-sign-guarded.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\HsmSignerInterface;
use NextPDF\Exception\NextPdfException;
use Psr\Log\LoggerInterface;
final readonly class HsmSigningService
{
public function __construct(
private HsmSignerInterface $signer,
private LoggerInterface $logger,
) {}
/**
* Sign data on the token through the Core HSM contract.
*
* The byte range is computed by the engine, never accepted from the
* caller. The token performs the signing operation; the private key
* does not leave the device.
*
* @param string $data The bytes the orchestrator hands to the token.
* @param string $algorithm The OpenSSL-style signing algorithm identifier.
*
* @throws NextPdfException When the token operation fails.
*
* @return string The raw signature bytes returned by the token.
*/
public function sign(string $data, string $algorithm): string
{
try {
return $this->signer->sign($data, $algorithm);
} catch (NextPdfException $e) {
// Structural message only — never the PIN or key material.
$this->logger->error('HSM signing failed', ['reason' => $e->getMessage()]);
throw $e;
}
}
}

Bestätigen Sie das Ergebnis so, wie es ein Prüfer täte:

  1. Lesen Sie das Signer-Zertifikat und die Kette in DER-Form vom Signer zurück und bestätigen Sie, dass sie mit dem auf dem Token bereitgestellten Zertifikat übereinstimmen.
  2. Öffnen Sie das signierte PDF in einem mit Ihren Vertrauensankern konfigurierten Validator und bestätigen Sie, dass die Signatur als kryptografisch intakt gemeldet wird. Eine erzeugte Signatur ist keine verifizierte Signatur; die Vertrauensentscheidung gehört dem Prüfer und seinen Vertrauensankern, nicht dem Erzeuger.
  3. Bestätigen Sie für eine ECDSA-Signatur, dass die eingebettete Signatur DER-kodiert ist — der Signer konvertiert die rohe Ausgabe des Tokens für Sie, sodass ein Validator, der die rohe verkettete Form ablehnt, die eingebettete Signatur dennoch akzeptieren sollte.
  4. Bestätigen Sie, dass kein PIN, kein Token-Label und kein Schlüsselmaterial in Ihren Anwendungsprotokollen erscheint.
  • Der Schlüssel bleibt auf dem Token. Die zu signierenden Daten werden an den Token übergeben; die Signieroperation läuft innerhalb der Token-Grenze. Der private Schlüssel wird nie in den PHP-Speicher geladen.
  • Der PIN ist ein Geheimnis. Er ist ein sensibler Konstruktorparameter, von Protokollen und Serialisierung ausgenommen. Stellen Sie ihn aus einem Secret Manager bereit. Wiederholte fehlgeschlagene Re-Authentifizierung kann den PIN am Token sperren; der Token, nicht NextPDF, erzwingt diese Richtlinie.
  • Fail-closed. Ein Token- oder HSM-Fehler löst eine typisierte Ausnahme aus. Der Signer erzeugt kein unsigniertes oder teilweise signiertes Ergebnis und ersetzt nie einen schwächeren Algorithmus.
  • Algorithmenstärke. Stellen Sie RSA-Schlüssel von mindestens 2048 Bit und ECDSA-Kurven von mindestens 224-Bit-Ordnung bereit, die akzeptablen Mindestwerte für die Signaturerzeugung gemäß NIST SP 800-131A Rev.2 §3.
  • Post-Quantum-Signieren ist experimentell und standardmäßig deaktiviert. Ein Post-Quantum-Pfad existiert hinter einem expliziten Opt-in-Flag. Standardmäßige PDF-Advanced-Electronic-Signatures-(PAdES-)Langzeitarchivprofile erkennen Post-Quantum-Suiten noch nicht, und die meisten Viewer lehnen sie bei der Validierung ab. Aktivieren Sie es nicht für Produktions-PAdES-Signaturen.

Diese Seite betrifft kryptografisches Signieren und die Integration eines Hardware-Sicherheitsmoduls. Jede normative Quelle ist paraphrasiert; es wird kein normativer Text wiedergegeben. ### Schlüsselverwahrungsgrenze

NextPDF Enterprise integriert sich mit einem PKCS#11-Token oder HSM. Es speichert, erzeugt oder garantiert die Sicherheit des Signierschlüssels nicht. Die Schlüsselsicherheit hängt vom Token oder HSM, von der Bereitstellung und vom Betreiber ab — nicht von NextPDF Enterprise allein. Sie sind für die Token-Bereitstellung, die PIN-Handhabung, die Slot-Konfiguration und den Netzwerkschutz eines netzgebundenen HSM verantwortlich.

  • Erweiterung fehlt. Das Konstruieren des PKCS#11-Signers löst eine typisierte Operationsausnahme aus, wenn ext-pkcs11 nicht geladen ist. Prüfen Sie zuerst die Verfügbarkeit.
  • Zertifikat oder Schlüssel nicht per Label gefunden. Die Konstruktion oder das Signieren löst eine typisierte Ausnahme aus, die das fehlende Objekt benennt. Bestätigen Sie das Label und den Slot.
  • Bereits angemeldet. Wenn mehrere Signer-Instanzen ein gecachtes Modul für denselben Slot teilen, meldet sich der Signer ab und wieder an, um eine frische PIN-Verifizierung bereitzustellen — erforderlich bei Personal-Identity-Verification-Token mit einer „PIN every time”-Richtlinie.
  • Nicht unterstützter Algorithmus. Das Anfordern eines Algorithmus, den der Signer nicht zuordnet, löst einen Argumentfehler aus, statt mit einem Ersatz zu signieren.
  • Netzwerk-HSM nicht erreichbar. Ein Netzwerk- oder Gerätefehler löst eine typisierte Ausnahme aus; der Signer erzeugt nie still ein unsigniertes Dokument.

Diese Seite dokumentiert nur extern beobachtbares Verhalten und die unterstützte öffentliche API-Oberfläche. Interne Namespace-Pfade, Hilfsklassen, Mechanismentabellen, Runbook-Dateinamen und Ticket-Präfixe liegen außerhalb des Umfangs.