Signatur
Beschreibung
openssl_cms_sign liest den Inhalt der Eingabedatei, signiert ihn kryptografisch mit dem angegebenen Zertifikat und privatem Schlüssel und schreibt die signierte Nachricht in die Ausgabedatei. CMS (Cryptographic Message Syntax, RFC 5652) ist der Nachfolger von S/MIME und eignet sich für die sichere Signierung und Verschlüsselung von Nachrichten, Dokumenten oder beliebigen Daten.
Die Funktion ist der älteren openssl_pkcs7_sign sehr ähnlich, arbeitet jedoch mit dem moderneren CMS-Standard. Über den Parameter $encoding kann das Ausgabeformat gewählt werden: S/MIME (OPENSSL_ENCODING_SMIME), DER (OPENSSL_ENCODING_DER) oder PEM (OPENSSL_ENCODING_PEM).
Typische Einsatzgebiete sind das Signieren von E-Mails (S/MIME), das Erstellen signierter Dokumente oder die gegenseitige Authentifizierung in verteilten Systemen. Über den optionalen Parameter $untrusted_certificates_filename können zusätzliche Zertifikate (z. B. Zwischenzertifikate der CA-Kette) in die Signatur eingebettet werden.
Mit dem Parameter $flags lässt sich das Verhalten der Funktion steuern, beispielsweise ob das Zertifikat in die Signatur eingebettet (OPENSSL_CMS_DETACHED) oder ob der Inhalt getrennt gehalten werden soll. Der Parameter $headers ermöglicht das Hinzufügen von MIME-Headern zur signierten Nachricht.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $input_filename Pflicht | string | Pfad zur Eingabedatei, deren Inhalt signiert werden soll. | |
| $output_filename Pflicht | string | Pfad zur Ausgabedatei, in die die signierte CMS-Nachricht geschrieben wird. | |
| $certificate Pflicht | OpenSSLCertificate|string | Das X.509-Zertifikat des Unterzeichners, entweder als OpenSSLCertificate-Ressource oder als PEM-kodierten String (mit Präfix file:// für Dateipfade). |
|
| $private_key Pflicht | OpenSSLAsymmetricKey|OpenSSLCertificate|array|string | Der zum Zertifikat passende private Schlüssel. Kann als OpenSSLAsymmetricKey, als PEM-String, als Dateipfad mit file:// oder als Array [key, passphrase] angegeben werden. |
|
| $headers Pflicht | ?array | null | Assoziatives Array mit zusätzlichen MIME-Headern, die der signierten Nachricht vorangestellt werden (z. B. ['To' => 'empfaenger@example.com']). Kann null sein. |
| $flags | int | 0 | Bitmaske aus OPENSSL_CMS_*-Konstanten zur Steuerung des Signiervorgangs, z. B. OPENSSL_CMS_DETACHED für eine abgetrennte Signatur oder OPENSSL_CMS_NOCERTS um das Zertifikat nicht einzubetten. |
| $encoding | int | OPENSSL_ENCODING_SMIME | Ausgabeformat der signierten Nachricht: OPENSSL_ENCODING_SMIME (Standard), OPENSSL_ENCODING_DER oder OPENSSL_ENCODING_PEM. |
| $untrusted_certificates_filename | ?string | null | Optionaler Pfad zu einer PEM-Datei mit zusätzlichen (nicht vertrauenswürdigen) Zertifikaten, z. B. Zwischenzertifikaten der CA-Kette, die in die Signatur eingebettet werden. |
Rückgabewert
true bei Erfolg zurück, false bei einem Fehler (z. B. ungültiger Schlüssel, nicht lesbare Eingabedatei oder nicht schreibbare Ausgabedatei).Beispiele
Einfache CMS-Signierung einer Textdatei im S/MIME-Format
<?php
// Zertifikat und privaten Schlüssel laden
$cert = file_get_contents('/pfad/zum/zertifikat.pem');
$privateKey = file_get_contents('/pfad/zum/privater_schluessel.pem');
// Eingabedatei erstellen
file_put_contents('/tmp/nachricht.txt', 'Das ist eine signierte Nachricht.');
// MIME-Header definieren
$headers = [
'From' => 'absender@example.com',
'To' => 'empfaenger@example.com',
'Subject' => 'Signierte Nachricht',
];
// Datei signieren
$erfolg = openssl_cms_sign(
'/tmp/nachricht.txt',
'/tmp/nachricht_signiert.eml',
$cert,
$privateKey,
$headers
);
if ($erfolg) {
echo "Datei erfolgreich signiert.\n";
echo file_get_contents('/tmp/nachricht_signiert.eml');
} else {
echo "Fehler beim Signieren: " . openssl_error_string() . "\n";
}
CMS-Signierung mit DER-Ausgabe und eingebetteter CA-Kette
<?php
// Zertifikat und Schlüssel als Ressourcen laden
$cert = openssl_x509_read(file_get_contents('/pfad/zum/zertifikat.pem'));
$privateKey = openssl_pkey_get_private(file_get_contents('/pfad/zum/privater_schluessel.pem'), 'geheimesPasswort');
file_put_contents('/tmp/dokument.txt', 'Wichtiges Dokument zum Signieren.');
// Abgetrennte Signatur im DER-Format, mit Zwischenzertifikat
$erfolg = openssl_cms_sign(
'/tmp/dokument.txt',
'/tmp/dokument_signiert.der',
$cert,
$privateKey,
null,
OPENSSL_CMS_DETACHED,
OPENSSL_ENCODING_DER,
'/pfad/zum/zwischenzertifikat.pem'
);
if ($erfolg) {
echo "DER-signierte Datei erstellt: " . filesize('/tmp/dokument_signiert.der') . " Bytes\n";
} else {
while ($fehler = openssl_error_string()) {
echo "OpenSSL-Fehler: $fehler\n";
}
}
// Wichtig · Fallstricke
Sicherheitshinweis: Der private Schlüssel sollte niemals im Webroot oder in versionierten Verzeichnissen gespeichert werden. Verwende restriktive Dateisystemberechtigungen (z. B. chmod 600) und speichere Schlüssel außerhalb des öffentlich zugänglichen Bereichs.
Zertifikatsvalidierung: openssl_cms_sign prüft nicht, ob das Zertifikat noch gültig oder widerrufen ist. Diese Prüfung muss separat z. B. mit openssl_x509_checkpurpose erfolgen.
PHP-Version: Diese Funktion ist seit PHP 8.0.0 verfügbar und ersetzt in modernen Anwendungen die ältere openssl_pkcs7_sign-Funktion. Für PHP-Versionen unter 8.0 muss stattdessen openssl_pkcs7_sign verwendet werden.
Fehlerbehandlung: Im Fehlerfall gibt die Funktion false zurück. Detaillierte Fehlermeldungen können mit openssl_error_string (ggf. mehrfach aufrufen) abgerufen werden.