Start · Sprachen · PHP · Referenz · openssl_cms_verify

openssl_cms_verify

Funktion

Überprüft die digitale Signatur einer CMS/PKCS#7-Nachricht und stellt sicher, dass sie von einem vertrauenswürdigen Zertifikat stammt.

seit PHP 8.0.0 Kategorie: crypto

Signatur

openssl_cms_verify(string $input_filename, int $flags, ?string $certificates = null, array $ca_info = [], ?string $untrusted_certificates_filename = null, ?string $content = null, ?string $pk7 = null, ?string $sigfile = null, int $encoding = OPENSSL_ENCODING_SMIME): bool

Beschreibung

openssl_cms_verify() prüft die Signatur einer CMS-Nachricht (Cryptographic Message Syntax, auch bekannt als PKCS#7 S/MIME). Die Funktion liest eine signierte Nachricht aus einer Datei und überprüft sowohl die kryptografische Integrität als auch die Vertrauenskette des verwendeten Zertifikats.

CMS-Signaturen werden häufig in sicheren E-Mail-Kommunikationen (S/MIME), in Software-Distributionspaketen und in anderen Szenarien eingesetzt, in denen digitale Signaturen und Nachrichtenverschlüsselung benötigt werden. Die Funktion unterstützt unterschiedliche Kodierungsformate: OPENSSL_ENCODING_SMIME für S/MIME, OPENSSL_ENCODING_DER für binäres DER-Format sowie OPENSSL_ENCODING_PEM für PEM-kodierte Daten.

Über den Parameter $flags lässt sich das Verhalten der Überprüfung steuern. Beispielsweise kann mit PKCS7_NOVERIFY die Zertifikatskettenprüfung übersprungen werden (nur für Testzwecke!), oder mit PKCS7_NOSIGS werden Signaturen gar nicht geprüft. Über $ca_info können eigene Vertrauensanker (CA-Zertifikate) übergeben werden, was in Unternehmensumgebungen mit eigenen PKI-Infrastrukturen essenziell ist.

Der optionale Parameter $content gibt einen Dateipfad an, in den der entschlüsselte Nachrichteninhalt geschrieben wird. Mit $pk7 kann die extrahierte CMS-Struktur gespeichert werden. Dies ist nützlich, um nach erfolgreicher Verifikation die Zertifikate oder den signierten Inhalt weiterzuverarbeiten.

Parameter

Name Typ Default Beschreibung
$input_filename Pflicht string Pfad zur Datei, die die zu prüfende CMS/PKCS#7-Nachricht enthält.
$flags Pflicht int Bitmaske aus PKCS7_*-Konstanten, die das Verhalten der Verifikation steuern. Häufig verwendete Werte: PKCS7_NOVERIFY, PKCS7_NOCHAIN, PKCS7_TEXT. Für eine vollständige Prüfung 0 übergeben.
$certificates ?string null Pfad zu einer Datei, in die die im CMS enthaltenen Zertifikate des Signierers geschrieben werden. Nützlich zur späteren Inspektion der Signer-Zertifikate.
$ca_info array [] Array mit Pfaden zu vertrauenswürdigen CA-Zertifikaten oder -Verzeichnissen, gegen die die Zertifikatskette geprüft wird. Entspricht dem cainfo-Parameter anderer OpenSSL-Funktionen.
$untrusted_certificates_filename ?string null Pfad zu einer Datei mit zusätzlichen, nicht vertrauenswürdigen Zwischenzertifikaten, die bei der Kettenverifizierung verwendet werden können.
$content ?string null Pfad zu einer Ausgabedatei, in die der entschlüsselte Klartextinhalt der Nachricht geschrieben wird. Wird ignoriert, wenn null.
$pk7 ?string null Pfad zu einer Ausgabedatei, in die die extrahierte CMS/PKCS#7-Struktur geschrieben wird.
$sigfile ?string null Pfad zur Signatur-Datei, wenn die Signatur vom Inhalt getrennt vorliegt (Detached Signature). Nur in Verbindung mit PKCS7_DETACHED relevant.
$encoding int OPENSSL_ENCODING_SMIME Gibt das Kodierungsformat der Eingabedatei an. Mögliche Werte: OPENSSL_ENCODING_SMIME, OPENSSL_ENCODING_DER, OPENSSL_ENCODING_PEM.

Rückgabewert

Typ
bool
Beschreibung
Gibt true zurück, wenn die Signatur gültig ist und die Zertifikatskette erfolgreich geprüft werden konnte. Gibt false zurück, wenn die Verifikation fehlschlägt (ungültige Signatur, nicht vertrauenswürdiges Zertifikat, abgelaufenes Zertifikat usw.).

Beispiele

Einfache CMS-Signaturprüfung gegen System-CA-Store

<?php
$inputFile  = '/pfad/zur/signierten_nachricht.eml';
$outputFile = '/pfad/zur/ausgabe_inhalt.txt';
$certFile   = '/pfad/zur/signer_zertifikate.pem';

$result = openssl_cms_verify(
    $inputFile,
    0,                  // vollständige Prüfung
    $certFile,          // Signer-Zertifikate extrahieren
    [],                 // System-CA-Verzeichnis verwenden
    null,
    $outputFile,        // Klartext-Inhalt speichern
    null,
    null,
    OPENSSL_ENCODING_SMIME
);

if ($result) {
    echo "Signatur ist gültig." . PHP_EOL;
    echo "Nachrichteninhalt wurde nach: " . $outputFile . " geschrieben." . PHP_EOL;
} else {
    $errors = openssl_error_string();
    echo "Signaturprüfung fehlgeschlagen: " . $errors . PHP_EOL;
}
Signatur ist gültig. Nachrichteninhalt wurde nach: /pfad/zur/ausgabe_inhalt.txt geschrieben.

CMS-Verifikation mit eigenem CA-Zertifikat (interne PKI)

<?php
$inputFile    = '/pfad/zur/cms_nachricht.der';
$internalCA   = '/etc/ssl/internal/ca-bundle.pem';
$contentOut   = '/tmp/verified_content.txt';

// Eigenes CA-Zertifikat für interne PKI-Infrastruktur verwenden
$result = openssl_cms_verify(
    $inputFile,
    PKCS7_NOCHAIN,       // keine externe Kettenprüfung, nur eigene CA
    null,
    [$internalCA],       // eigene CA als Vertrauensanker
    null,
    $contentOut,
    null,
    null,
    OPENSSL_ENCODING_DER
);

if ($result) {
    echo "CMS-Signatur durch interne CA verifiziert." . PHP_EOL;
    echo "Inhalt: " . file_get_contents($contentOut) . PHP_EOL;
} else {
    while ($msg = openssl_error_string()) {
        echo "OpenSSL-Fehler: " . $msg . PHP_EOL;
    }
}
CMS-Signatur durch interne CA verifiziert. Inhalt: Dies ist der signierte Nachrichtentext.

// Wichtig · Fallstricke

Sicherheitshinweise:

  • Niemals PKCS7_NOVERIFY in Produktionsumgebungen verwenden – dies deaktiviert die Zertifikatsverifikation vollständig und macht die Signaturprüfung wirkungslos gegenüber gefälschten Signaturen.
  • Stelle sicher, dass der CA-Store aktuell ist und keine widerrufenen Zertifikate (CRL/OCSP) akzeptiert werden. openssl_cms_verify() prüft standardmäßig keine Sperrlisten.
  • Die Funktion wurde in PHP 8.0 eingeführt und ist das CMS-Äquivalent zur älteren Funktion openssl_pkcs7_verify(), die weiterhin für PKCS#7/S/MIME-Kompatibilität existiert.
  • Temporäre Ausgabedateien (z. B. für $content) sollten in gesicherten Verzeichnissen mit restriktiven Dateisystemberechtigungen abgelegt werden, um unbefugten Zugriff zu verhindern.
  • Bei einem Rückgabewert von false sollte stets openssl_error_string() in einer Schleife aufgerufen werden, um alle ausstehenden OpenSSL-Fehlermeldungen aus dem internen Fehlerpuffer zu lesen.