Signatur
Beschreibung
openssl_pkcs7_sign liest eine E-Mail-Nachricht oder beliebige Daten aus input_filename, signiert sie kryptografisch mit dem angegebenen Zertifikat und privatem Schlüssel und schreibt das Ergebnis in output_filename. Das erzeugte Format ist PKCS#7/S/MIME und wird von gängigen E-Mail-Clients (Outlook, Thunderbird, Apple Mail) unterstützt, um die Authentizität und Integrität der Nachricht zu verifizieren.
Die Signatur kann entweder detached (Standard, PKCS7_DETACHED) oder eingebettet erzeugt werden. Bei detached Signatures bleibt die ursprüngliche Nachricht für nicht-S/MIME-fähige Clients lesbar. Über den Parameter headers können zusätzliche MIME-Header (z. B. From, To, Subject) in die Ausgabedatei eingefügt werden.
Mit untrusted_certificates_filename lässt sich optional ein PEM-Bündel mit Zwischenzertifikaten angeben, die der Empfänger zur Verifikation der Zertifikatskette benötigt. Dies ist wichtig, wenn das Signierzertifikat nicht von einer allgemein bekannten Root-CA direkt ausgestellt wurde.
Typische Anwendungsgebiete sind das automatische Signieren von ausgehenden E-Mails in Unternehmensanwendungen, die Erzeugung rechtssicher nachweisbarer elektronischer Dokumente sowie die Bereitstellung von S/MIME-gesicherten Benachrichtigungen aus Webanwendungen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $input_filename Pflicht | string | Pfad zur Eingabedatei, die die zu signierende Nachricht enthält (üblicherweise eine rohe E-Mail oder ein MIME-Dokument). | |
| $output_filename Pflicht | string | Pfad zur Ausgabedatei, in die die signierte PKCS#7/S/MIME-Nachricht geschrieben wird. | |
| $certificate Pflicht | OpenSSLCertificate|string | Das X.509-Signierzertifikat als OpenSSLCertificate-Ressource, PEM-String oder Dateipfad im Format file://pfad/zur/cert.pem. |
|
| $private_key Pflicht | OpenSSLAsymmetricKey|OpenSSLCertificate|array|string | Der zum Zertifikat gehörende private Schlüssel. Kann als OpenSSLAsymmetricKey-Ressource, PEM-String, Dateipfad (file://...) oder als Array [key, passphrase] für passwortgeschützte Schlüssel übergeben werden. |
|
| $headers Pflicht | ?array | null | Assoziatives Array mit MIME-Headern, die der Ausgabedatei vorangestellt werden (z. B. ['From' => 'sender@example.com', 'Subject' => 'Test']). Kann null sein, wenn keine Header hinzugefügt werden sollen. |
| $flags | int | PKCS7_DETACHED | Bitmaske aus PKCS7_*-Konstanten, die das Signierverhalten steuern. PKCS7_DETACHED erzeugt eine externe Signatur; PKCS7_TEXT konvertiert den Nachrichtentyp auf text/plain. |
| $untrusted_certificates_filename | ?string | null | Optionaler Pfad zu einer PEM-Datei mit Zwischenzertifikaten (Intermediate CA Certificates), die in die signierte Nachricht eingebettet werden, damit der Empfänger die vollständige Zertifikatskette aufbauen kann. |
Rückgabewert
true bei Erfolg zurück. Im Fehlerfall wird false zurückgegeben, z. B. wenn Eingabedatei nicht lesbar, Ausgabedatei nicht schreibbar, Zertifikat oder Schlüssel ungültig oder Schlüssel und Zertifikat nicht zusammenpassen.Beispiele
Einfaches Signieren einer E-Mail-Nachricht
<?php
// Eingabedatei mit roher E-Mail-Nachricht vorbereiten
$inputFile = '/tmp/mail_input.eml';
$outputFile = '/tmp/mail_signed.eml';
file_put_contents($inputFile, "Content-Type: text/plain\r\n\r\nHello, this is a signed message.");
// Zertifikat und privaten Schlüssel laden
$certPem = file_get_contents('/etc/ssl/my_cert.pem');
$privateKey = ['file:///etc/ssl/my_key.pem', 'geheimesPasswort'];
$headers = [
'From' => 'sender@example.com',
'To' => 'recipient@example.com',
'Subject' => 'Signierte Testnachricht',
];
$result = openssl_pkcs7_sign(
$inputFile,
$outputFile,
$certPem,
$privateKey,
$headers,
PKCS7_DETACHED
);
if ($result) {
echo "Nachricht erfolgreich signiert: " . $outputFile . PHP_EOL;
} else {
echo "Fehler beim Signieren!" . PHP_EOL;
while ($msg = openssl_error_string()) {
echo $msg . PHP_EOL;
}
}
Signieren mit Zwischenzertifikaten für vollständige Zertifikatskette
<?php
$inputFile = '/tmp/document.eml';
$outputFile = '/tmp/document_signed.eml';
$intermCaFile = '/etc/ssl/intermediate_ca_bundle.pem';
file_put_contents($inputFile, "Content-Type: text/plain\r\n\r\nDokument mit vollständiger Zertifikatskette.");
$cert = 'file:///etc/ssl/my_cert.pem';
$privateKey = 'file:///etc/ssl/my_key_nopass.pem';
$headers = [
'From' => 'noreply@company.com',
'To' => 'partner@external.com',
'Subject' => 'Offizielles Dokument',
];
$success = openssl_pkcs7_sign(
$inputFile,
$outputFile,
$cert,
$privateKey,
$headers,
PKCS7_DETACHED,
$intermCaFile
);
if ($success) {
echo "Signiert mit eingebetteter Zertifikatskette." . PHP_EOL;
echo "Ausgabegröße: " . filesize($outputFile) . " Bytes" . PHP_EOL;
} else {
foreach (openssl_error_string() ? [openssl_error_string()] : [] as $err) {
echo "OpenSSL-Fehler: $err" . PHP_EOL;
}
}
// Wichtig · Fallstricke
Sicherheitshinweise:
- Der private Schlüssel sollte niemals im Web-Root oder in einem über HTTP erreichbaren Verzeichnis gespeichert werden. Verwende restriktive Dateisystemberechtigungen (z. B.
chmod 400). - Passwörter für passwortgeschützte Schlüssel sollten aus Umgebungsvariablen oder einem sicheren Secret-Store gelesen werden, nicht hartcodiert im Quellcode stehen.
- Temporäre Eingabe- und Ausgabedateien in
/tmpsollten nach Verwendung mitunlink()gelöscht werden, insbesondere auf geteilten Systemen. - Stelle sicher, dass Zertifikat und privater Schlüssel zusammenpassen – andernfalls schlägt die Funktion mit einem OpenSSL-Fehler fehl. Fehlermeldungen lassen sich über
openssl_error_string()in einer Schleife abfragen. - Ab PHP 8.0 werden Ressourcen für Schlüssel und Zertifikate durch dedizierte Objekte (
OpenSSLCertificate,OpenSSLAsymmetricKey) ersetzt; veralteteresource-Typen werden nicht mehr unterstützt.