Start · Sprachen · PHP · Referenz · stream_socket_enable_crypto

stream_socket_enable_crypto

Funktion

Schaltet Verschlüsselung (TLS/SSL) auf einem bereits verbundenen Stream-Socket ein oder aus.

seit PHP 5.1.0 Kategorie: io

Signatur

stream_socket_enable_crypto(resource $stream, bool $enable, int|null $crypto_method = null, resource|null $session_stream = null): int|bool

Beschreibung

stream_socket_enable_crypto() aktiviert oder deaktiviert die kryptografische Verschlüsselung auf einem Stream-Socket, der zuvor mit stream_socket_client() oder stream_socket_server() erstellt wurde. Die Funktion ist besonders nützlich, wenn eine Verbindung zunächst unverschlüsselt aufgebaut und später auf TLS/SSL hochgestuft werden soll – ein Vorgang, der als STARTTLS bekannt ist (z. B. bei SMTP, IMAP oder FTP).

Der Parameter $crypto_method legt das gewünschte Protokoll fest (z. B. STREAM_CRYPTO_METHOD_TLS_CLIENT). Wird er weggelassen, muss die Verschlüsselungsmethode zuvor über den Stream-Kontext mit der Option crypto_method festgelegt worden sein. Der optionale Parameter $session_stream erlaubt es, Sitzungsdaten eines anderen Streams wiederzuverwenden, um den TLS-Handshake zu beschleunigen.

Die Funktion gibt im nicht-blockierenden Modus 0 zurück, wenn der Handshake noch nicht abgeschlossen ist – in diesem Fall muss sie erneut aufgerufen werden. Im blockierenden Modus liefert sie true bei Erfolg und false bei einem Fehler.

Typische Einsatzszenarien sind selbst implementierte Mail-Clients, FTP-Bibliotheken oder andere Protokolle, bei denen der Wechsel von Klartext zu Verschlüsselung mitten in einer bestehenden Verbindung erfolgt.

Parameter

Name Typ Default Beschreibung
$stream Pflicht resource Ein gültiger Stream-Socket, der bereits verbunden ist (erstellt z. B. mit stream_socket_client() oder stream_socket_server()).
$enable Pflicht bool true, um Verschlüsselung zu aktivieren; false, um sie zu deaktivieren.
$crypto_method int|null null Die gewünschte Verschlüsselungsmethode. Mögliche Werte sind Konstanten wie STREAM_CRYPTO_METHOD_TLS_CLIENT, STREAM_CRYPTO_METHOD_TLS_SERVER, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT usw. Wird null übergeben, muss die Methode im Stream-Kontext definiert sein.
$session_stream resource|null null Ein optionaler Stream, dessen TLS-Sitzungsdaten wiederverwendet werden sollen, um den Handshake zu beschleunigen (Session Resumption).

Rückgabewert

Typ
int|bool
Beschreibung
Gibt true zurück, wenn Verschlüsselung erfolgreich aktiviert/deaktiviert wurde, false bei einem Fehler. Im nicht-blockierenden Modus wird 0 zurückgegeben, wenn der TLS-Handshake noch nicht abgeschlossen ist und die Funktion erneut aufgerufen werden muss.

Beispiele

STARTTLS mit einem SMTP-Server

<?php
$server = 'smtp.example.com';
$port   = 587;

// Unverschlüsselte Verbindung herstellen
$socket = stream_socket_client(
    "tcp://{$server}:{$port}",
    $errno,
    $errstr,
    30
);

if (!$socket) {
    die("Verbindungsfehler: $errstr ($errno)\n");
}

// Server-Begrüßung lesen
echo fgets($socket, 1024);

// EHLO senden
fwrite($socket, "EHLO localhost\r\n");
while ($line = fgets($socket, 1024)) {
    echo $line;
    if (substr($line, 3, 1) === ' ') break; // Letzte Antwortzeile
}

// STARTTLS anfordern
fwrite($socket, "STARTTLS\r\n");
echo fgets($socket, 1024);

// TLS-Handshake durchführen
$result = stream_socket_enable_crypto(
    $socket,
    true,
    STREAM_CRYPTO_METHOD_TLS_CLIENT
);

if ($result === true) {
    echo "TLS erfolgreich aktiviert.\n";
    // Ab hier verschlüsselt kommunizieren ...
} else {
    echo "TLS-Handshake fehlgeschlagen.\n";
}

fclose($socket);

Verschlüsselung auf einem nicht-blockierenden Socket aktivieren

<?php
$context = stream_context_create([
    'ssl' => [
        'verify_peer'       => true,
        'verify_peer_name'  => true,
        'cafile'            => '/etc/ssl/certs/ca-certificates.crt',
    ]
]);

$socket = stream_socket_client(
    'tcp://example.com:443',
    $errno,
    $errstr,
    30,
    STREAM_CLIENT_CONNECT,
    $context
);

if (!$socket) {
    die("Verbindungsfehler: $errstr ($errno)\n");
}

// Nicht-blockierenden Modus aktivieren
stream_set_blocking($socket, false);

// Handshake-Schleife für nicht-blockierenden Modus
do {
    $result = stream_socket_enable_crypto(
        $socket,
        true,
        STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
    );
    if ($result === false) {
        die("TLS-Fehler aufgetreten.\n");
    }
    // 0 bedeutet: Handshake noch nicht abgeschlossen
} while ($result === 0);

echo "TLS-Verbindung hergestellt.\n";

// HTTPS-Anfrage senden
fwrite($socket, "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n");
stream_set_blocking($socket, true);
echo stream_get_contents($socket);

fclose($socket);

// Wichtig · Fallstricke

Sicherheitshinweis: Deaktivieren Sie niemals die Peer-Verifizierung (verify_peer und verify_peer_name) in Produktionsumgebungen, da dies die Verbindung anfällig für Man-in-the-Middle-Angriffe macht.

Protokollwahl: Bevorzugen Sie STREAM_CRYPTO_METHOD_TLS_CLIENT (welches automatisch TLS 1.0–1.3 umfasst, je nach PHP- und OpenSSL-Version) gegenüber veralteten Konstanten wie STREAM_CRYPTO_METHOD_SSLv3_CLIENT, da SSLv2 und SSLv3 als unsicher gelten und in modernen PHP-/OpenSSL-Versionen nicht mehr unterstützt werden.

Reihenfolge beachten: Die Funktion darf erst aufgerufen werden, wenn die Verbindung vollständig hergestellt ist. Bei STARTTLS-Protokollen muss zuerst der protokollspezifische Handshake (z. B. STARTTLS-Kommando bei SMTP) abgeschlossen sein, bevor TLS aktiviert wird.

Wenn $enable auf false gesetzt wird, wird Verschlüsselung deaktiviert – dies ist in den meisten Protokollen nicht vorgesehen und kann zu unerwarteten Sicherheitsproblemen führen.