Start · Sprachen · PHP · Referenz · openssl_pkcs7_encrypt

openssl_pkcs7_encrypt

Funktion

Verschlüsselt eine Datei als S/MIME-Nachricht mit dem öffentlichen Schlüssel eines oder mehrerer Empfänger-Zertifikate.

seit PHP 4.0.6 Kategorie: crypto

Signatur

openssl_pkcs7_encrypt(string $input_filename, string $output_filename, OpenSSLCertificate|string|array $certificate, ?array $headers, int $flags = 0, int $cipher_algo = OPENSSL_CIPHER_AES_128_CBC): bool

Beschreibung

openssl_pkcs7_encrypt liest den Klartext aus der Datei input_filename, verschlüsselt ihn nach dem S/MIME-Standard (PKCS#7 / CMS) und schreibt das Ergebnis in output_filename. Die Verschlüsselung nutzt den öffentlichen Schlüssel des angegebenen Empfänger-Zertifikats, sodass nur der Inhaber des zugehörigen privaten Schlüssels die Nachricht entschlüsseln kann.

Typische Anwendungsfälle sind das sichere Versenden von E-Mails mit vertraulichem Inhalt (z. B. über PHPs mail()-Funktion) sowie die Ablage von sensitiven Daten in einem PKCS#7-Container. Mehrere Empfänger werden unterstützt, indem ein Array von Zertifikaten übergeben wird — jeder Empfänger erhält dann seinen eigenen verschlüsselten Session-Key.

Über den Parameter headers können beliebige MIME-Header (z. B. To, From, Subject) in die Ausgabedatei eingefügt werden. Der Parameter cipher_algo bestimmt den symmetrischen Algorithmus, mit dem der eigentliche Nachrichteninhalt verschlüsselt wird; empfohlen wird mindestens OPENSSL_CIPHER_AES_256_CBC.

Die Funktion setzt eine korrekt konfigurierte OpenSSL-Extension voraus und schreibt den Output im PEM-codierten S/MIME-Format, das direkt als Rumpf einer verschlüsselten E-Mail verwendet werden kann.

Parameter

Name Typ Default Beschreibung
$input_filename Pflicht string Pfad zur Eingabedatei, die den zu verschlüsselnden Klartext enthält (i. d. R. eine MIME-Nachricht oder reiner Text).
$output_filename Pflicht string Pfad zur Ausgabedatei, in die das S/MIME-verschlüsselte Ergebnis geschrieben wird.
$certificate Pflicht OpenSSLCertificate|string|array Das X.509-Empfängerzertifikat (oder ein Array von Zertifikaten). Kann ein OpenSSLCertificate-Objekt, ein PEM-String oder ein Dateipfad (mit dem Präfix file://) sein.
$headers Pflicht ?array null Assoziatives Array mit MIME-Headern (z. B. ['To' => 'empfaenger@example.com', 'Subject' => 'Vertraulich']), die dem verschlüsselten Output vorangestellt werden. null fügt keine zusätzlichen Header ein.
$flags int 0 Bitmaske aus PKCS7_*-Konstanten (z. B. PKCS7_TEXT), um das Verhalten der Verschlüsselung zu steuern. Standard ist 0.
$cipher_algo int OPENSSL_CIPHER_AES_128_CBC Symmetrischer Verschlüsselungsalgorithmus für den Nachrichteninhalt. Verfügbare Konstanten: OPENSSL_CIPHER_AES_128_CBC, OPENSSL_CIPHER_AES_256_CBC, OPENSSL_CIPHER_3DES u. a. Empfohlen: OPENSSL_CIPHER_AES_256_CBC.

Rückgabewert

Typ
bool
Beschreibung
Gibt true zurück, wenn die Verschlüsselung erfolgreich war und die Ausgabedatei geschrieben wurde. Bei einem Fehler (ungültiges Zertifikat, nicht schreibbare Datei usw.) wird false zurückgegeben; Details können über openssl_error_string() abgerufen werden.

Beispiele

Einfache S/MIME-Verschlüsselung einer E-Mail

<?php
// Empfängerzertifikat laden (PEM-Datei)
$certPem = file_get_contents('/pfad/zu/empfaenger.crt');

// Klartext in temporäre Eingabedatei schreiben
$inputFile  = tempnam(sys_get_temp_dir(), 'smime_in_');
$outputFile = tempnam(sys_get_temp_dir(), 'smime_out_');

file_put_contents($inputFile, "Dies ist eine vertrauliche Nachricht.");

$headers = [
    'To'      => 'empfaenger@example.com',
    'From'    => 'absender@example.com',
    'Subject' => 'Vertrauliche Mitteilung',
];

$result = openssl_pkcs7_encrypt(
    $inputFile,
    $outputFile,
    $certPem,
    $headers,
    0,
    OPENSSL_CIPHER_AES_256_CBC
);

if ($result) {
    echo "Verschlüsselung erfolgreich.\n";
    // Inhalt von $outputFile kann direkt als E-Mail-Body genutzt werden
    echo file_get_contents($outputFile);
} else {
    echo "Fehler: " . openssl_error_string() . "\n";
}

unlink($inputFile);
unlink($outputFile);
Verschlüsselung erfolgreich. MIME-Version: 1.0 Content-Disposition: attachment; filename="smime.p7m" Content-Type: application/x-pkcs7-mime; smime-type=enveloped-data; name="smime.p7m" Content-Transfer-Encoding: base64 ...

Verschlüsselung für mehrere Empfänger

<?php
// Zwei Empfängerzertifikate
$cert1 = file_get_contents('/pfad/zu/empfaenger1.crt');
$cert2 = file_get_contents('/pfad/zu/empfaenger2.crt');

$inputFile  = tempnam(sys_get_temp_dir(), 'smime_in_');
$outputFile = tempnam(sys_get_temp_dir(), 'smime_out_');

file_put_contents($inputFile, "Nachricht an zwei Empfänger.");

$headers = [
    'To'      => 'empf1@example.com, empf2@example.com',
    'Subject' => 'Gruppenmail verschlüsselt',
];

// Array mit mehreren Zertifikaten übergeben
$ok = openssl_pkcs7_encrypt(
    $inputFile,
    $outputFile,
    [$cert1, $cert2],
    $headers,
    0,
    OPENSSL_CIPHER_AES_256_CBC
);

if ($ok) {
    echo "Nachricht erfolgreich für beide Empfänger verschlüsselt.\n";
} else {
    while ($err = openssl_error_string()) {
        echo "OpenSSL-Fehler: $err\n";
    }
}

unlink($inputFile);
unlink($outputFile);
Nachricht erfolgreich für beide Empfänger verschlüsselt.

// Wichtig · Fallstricke

Algorithmuswahl: Der Standardalgorithmus OPENSSL_CIPHER_AES_128_CBC gilt als ausreichend sicher, für neue Anwendungen wird jedoch OPENSSL_CIPHER_AES_256_CBC empfohlen. Veraltete Algorithmen wie OPENSSL_CIPHER_DES oder OPENSSL_CIPHER_3DES sollten nicht mehr verwendet werden.

Temporäre Dateien: Eingabe- und Ausgabedaten werden als Dateien auf dem Dateisystem zwischengespeichert. Achte darauf, diese temporären Dateien nach der Verwendung sicher zu löschen (unlink()), um ein versehentliches Lesen des Klartexts zu verhindern.

Zertifikat vs. Schlüssel: Diese Funktion benötigt ausschließlich das öffentliche Zertifikat des Empfängers — niemals den privaten Schlüssel. Zum Entschlüsseln wird hingegen openssl_pkcs7_decrypt mit dem privaten Schlüssel benötigt.

Signierung und Verschlüsselung kombinieren: Soll eine Nachricht sowohl signiert als auch verschlüsselt werden, erst mit openssl_pkcs7_sign signieren und dann das Ergebnis mit openssl_pkcs7_encrypt verschlüsseln.