Signatur
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
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;
}
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;
}
}
// Wichtig · Fallstricke
Sicherheitshinweise:
- Niemals
PKCS7_NOVERIFYin 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
falsesollte stetsopenssl_error_string()in einer Schleife aufgerufen werden, um alle ausstehenden OpenSSL-Fehlermeldungen aus dem internen Fehlerpuffer zu lesen.