Start · Sprachen · PHP · Referenz · openssl_cms_sign

openssl_cms_sign

Funktion

Signiert eine Datei mit CMS (Cryptographic Message Syntax) unter Verwendung eines X.509-Zertifikats und des zugehörigen privaten Schlüssels.

seit PHP 8.0.0 Kategorie: crypto

Signatur

openssl_cms_sign(string $input_filename, string $output_filename, OpenSSLCertificate|string $certificate, OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key, ?array $headers, int $flags = 0, int $encoding = OPENSSL_ENCODING_SMIME, ?string $untrusted_certificates_filename = null): bool

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

Typ
bool
Beschreibung
Gibt 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";
}
Datei erfolgreich signiert.

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";
    }
}
DER-signierte Datei erstellt: 1234 Bytes

// 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.