So wird’s gemacht: Schützen von Socketverbindungen mit TLS/SSL (HTML)

[ Dieser Artikel richtet sich an Windows 8.x- und Windows Phone 8.x-Entwickler, die Windows-Runtime-Apps schreiben. Wenn Sie für Windows 10 entwickeln, finden Sie weitere Informationen unter neueste Dokumentation]

In diesem Thema wird gezeigt, wie Sie Streamsocketverbindungen mit TLS/SSL schützen können, wenn Sie das Feature StreamSocket in einer Windows Store-App verwenden.

Wissenswertes

Technologien

Voraussetzungen

  • Die folgenden Beispiele in diesem Thema sind in JavaScript verfasst. Grundkenntnisse in Sockets und der Verwendung von SSL/TLS werden empfohlen.

Übersicht über eine SSL/TLS-Verbindung

Secure Sockets Layer (SSL) und das aktuellere Transport Layer Security (TLS) sind Verschlüsselungsprotokolle für die Authentifizierung und Verschlüsselung der Kommunikation in Netzwerken. Diese Protokolle dienen dazu, das Mitverfolgen und Manipulieren von Daten zu verhindern, die im Netzwerk gesendet und empfangen werden. Für den Protokollaustausch wird dabei ein Client-Server-Modell verwendet. Diese Protokolle verwenden zudem digitale Zertifikate und Zertifizierungsstellen, um den jeweiligen Server zu identifizieren. Das TLS-Protokoll wird in IETF RFC 5246 dokumentiert. Das frühere SSL-Protokoll wurde von Netscape Communications dokumentiert. SSL bezieht sich im allgemeinen Sprachgebrauch auf beide Protokolle.

Das StreamSocket-Objekt kann für die Verwendung von SSL/TLS für die Kommunikation zwischen dem Client und dem Server konfiguriert werden. Diese Unterstützung für SSL/TLS beschränkt sich auf die Verwendung des StreamSocket-Objekts als Client in der SSL/TLS-Aushandlung. SSL/TLS kann derzeit bei einer eingehenden Verbindung nicht vom StreamSocketListener für den erstellten StreamSocket verwendet werden, um SSL/TLS für den erstellten StreamSocket zu aktivieren. Denn die serverseitige SSL/TLS-Aushandlung ist für einen StreamSocket nicht implementiert. Die Clientunterstützung für SSL/TLS beinhaltet nicht die Verwendung von Clientzertifikaten.

Es gibt zwei Möglichkeiten, um eine StreamSocket-Verbindung mit SSL/TLS zu sichern:

  • ConnectAsync – Stellt die erste Verbindung mit einem Netzwerkdienst her und handelt sofort die Verwendung von SSL/TLS für jede Kommunikation aus.
  • UpgradeToSslAsync – Stellt die erste Verbindung mit einem Netzwerk ohne Verschlüsselung her. Die App kann Daten senden oder empfangen. Dann wird die Verbindung für die Verwendung von SSL/TLS für jede weitere Verbindung hochgestuft.

Verwenden von "ConnectAsync"

Stellt die erste Verbindung mit einem Netzwerkdienst her und handelt dann sofort die Verwendung von SSL/TLS für jede Kommunikation aus. Es gibt zwei ConnectAsync-Methoden, die das Übergeben eines protectionLevel-Parameters unterstützen:

Wenn beim Aufruf einer der obigen ConnectAsync-Methoden der protectionLevel-Parameter auf Windows.Networking.Sockets.SocketProtectionLevel.Ssl festgelegt ist, muss der StreamSocket SSL/TLS für die Verschlüsselung verwenden. Dieser Wert erfordert eine Verschlüsselung, und eine NULL-Verschlüsselung ist nie zulässig.

Der übliche Ablauf ist bei beiden ConnectAsync-Methoden gleich.

  • Erstellen Sie einen StreamSocket.
  • Wenn eine erweiterte Option für den Socket erforderlich ist, rufen Sie mit der StreamSocket.Control-Eigenschaft die StreamSocketControl-Instanz ab, die einem StreamSocket-Objekt zugeordnet ist. Legen Sie eine Eigenschaft für StreamSocketControl fest.
  • Rufen Sie eine der obigen ConnectAsync-Methoden auf, um einen Vorgang zu starten, bei dem eine Verbindung mit einem Remoteziel hergestellt und sofort mit der Aushandlung von SSL/TLS begonnen wird.

Das folgende Beispiel erstellt einen StreamSocket und versucht, eine Verbindung mit dem Netzwerkdienst herzustellen und sofort die Verwendung von SSL/TLS auszuhandeln. Bei einer erfolgreichen Aushandlung wird jede Netzwerkkommunikation zwischen dem Client und dem Netzwerkserver verschlüsselt, bei der der StreamSocket verwendet wird.



    // Define some global variables that can be used from
    // multiple functions as needed 
    var clientSocket = null;
    var serverHostName = null;
    var serverServiceName = null;


    function openClient() {
        clientSocket = new Windows.Networking.Sockets.StreamSocket();
        // Try to connect to contoso using HTTPS (port 443)
        serverHostName = new Windows.Networking.HostName("www.contoso.com");
        serverServiceName = "https";

        // Call connectAsync method with SSL
        clientSocket.connectAsync(serverHostName, serverServiceName, Sockets.SocketProtectionLevel.Ssl).done(onClientAccept, onConnectError);
    }

    // For simplicity, the sample omits implementation of the
    // displayStatus method used to display status and error messages 

    // If the client connection was accepted, display
    // a message to the user
    function onClientAccept() {
        socketSample.displayStatus("Client: connection completed.");
    }

    // The connection failed so display an error message
    // Could retry the connection, but for this simple example
    // just close the socket.
    function onConnectError(reason) {
       socketsSample.displayStatus(reason);
       clientSocket.close();
       clientSocket = null; 
    }

Verwenden von "UpgradeToSslAsync"

Stellt eine erste Verbindung mit einem Netzwerk ohne Verschlüsselung her. Die App kann einige Daten senden oder empfangen. Dann wird die Verbindung für die Verwendung von SSL/TLS für jede Kommunikation heraufgestuft. Dabei wird die folgende Methode verwendet:

Die UpgradeToSslAsync-Methode besitzt zwei Parameter. Der protectionLevel-Parameter gibt den gewünschten Schutzgrad an. Der validationHostName-Parameter ist der Hostname des Remotenetzwerkziels, der bei der Höherstufung auf SSL für die Validierung verwendet wird. In der Regel entspricht der validationHostName dem Hostnamen, mit dem die App die erste Verbindung hergestellt hat. Wenn beim Aufruf der obigen UpgradeToSslAsync-Methode der protectionLevel-Parameter auf Windows.System.Socket.SocketProtectionLevel.Ssl festgelegt ist, muss der StreamSocket SSL/TLS für die Verschlüsselung verwenden. Dieser Wert erfordert eine Verschlüsselung, und eine NULL-Verschlüsselung ist nie zulässig.

Der übliche Ablauf bei dieser UpgradeToSslAsync Methode lautet wie folgt:

  • Erstellen Sie einen StreamSocket.
  • Wenn eine erweiterte Option für den Socket erforderlich ist, rufen Sie mit der StreamSocket.Control-Eigenschaft die StreamSocketControl-Instanz ab, die einem StreamSocket-Objekt zugeordnet ist. Legen Sie eine Eigenschaft für StreamSocketControl fest.
  • Senden Sie jetzt alle Daten die gegebenenfalls unverschlüsselt gesendet oder empfangen werden müssen.
  • Rufen Sie die UpgradeToSslAsync-Methode auf, um einen Vorgang zum Höherstufen der Verbindung auf SSL/TLS zu starten.

Das folgende Beispiel erstellt einen StreamSocket, versucht, eine Verbindung mit dem Netzwerkdienst herzustellen, sendet einige erste Daten und handelt dann die Verwendung von SSL/TLS aus. Bei einer erfolgreichen Aushandlung wird jede Netzwerkkommunikation zwischen dem Client und dem Netzwerkserver verschlüsselt, bei der der StreamSocket verwendet wird.



    // Define some global variables that can be used from
    // multiple functions as needed
    var clientSocket = null;
    var serverHostName = null;
    var serverServiceName = null;

    function openClient() {
        clientSocket = new Windows.Networking.Sockets.StreamSocket();
        // Try to connect to contoso initially using HTTP
        serverHostName = new Windows.Networking.HostName("www.contoso.com");
        serverServiceName = "http";

        // Call ConnectAsync method to establish initial connection
        clientSocket.connectAsync(serverHostName, serverServiceName).done(onClientAccept, onConnectError);
    }

    // For simplicity, the sample omits implementation of the
    // displayStatus method used to display status and error messages 

    // If the client connection was accepted, display
    // a message to the user
    function onClientAccept() {
        socketSample.displayStatus("Client: connection completed.");
        sendHello();
    }

    // The connection failed so display an error message
    // We could retry the connection, but for this simple example
    // we just close the socket.
    function onConnectError(reason) {
        socketsSample.displayStatus(reason);
        clientSocket.close();
        clientSocket = null; 
    }

    // Send some data in a simple format that is
    // the length of the string of data in a 4-byte integer
    // followed by the string
    function sendHello() {
        if (!clientSocket) {
            socketsSample.displayStatus("Client: you must connect the client before using it.");
            return;
        }
        var writer = new Windows.Storage.Streams.DataWriter(socketsSample.clientSocket.outputStream);
        var string = "Hello World ☺ ";
        var len = writer.measureString(string); // Gets the UTF-8 string length.
        writer.writeInt32(len);
        writer.writeString(string);
        socketsSample.displayStatus("Client: sending hello.");
        writer.storeAsync().done(onStore, onSendError);
        writer.detachStream(); // Detach stream, if not, DataWriter destructor will close it.
    }

    function onStore() {
        socketsSample.displayStatus("Client: sent hello.");
        upgradeClient();
    }

    function onSendError(reason) {
        socketsSample.displayStatus(reason);
        clientSocket.close();
        clientSocket = null; 
    }

    function upgradeClient() {
        if (!clientSocket) {
            socketsSample.displayStatus("Client: you must connect the client before using it.");
            return;
        }
        var validationName = serverHostName;
        upgradeToSslAsync(SocketProtectionLevel.Ssl, serverHostName).done(onUpgradeAccept, onUpgradeError);
    }         

    // If upgrade to SSL was successful, display message to user
    function onUpgradeAccept() {
        socketSample.displayStatus("Client: upgrade to SSL completed.");
    }

    // The upgrade connection failed so display an error message
    // We could retry the upgrade possibly changing the validationHostname, 
    // but for this simple example we just close the socket.
    function onUpgradeError(reason) {
        socketsSample.displayStatus(reason);
        clientSocket.close();
        clientSocket = null; 
    }

Anmerkungen

Die SocketProtectionLevel-Enumeration verfügt über mehrere mögliche Werte:

  • PlainSocket – Ein einfacher Socket ohne Verschlüsselung.

  • Ssl – Ein Socket, der SSL/TLS zur Verschlüsselung verwenden muss. Dieser Wert erfordert eine Verschlüsselung, und eine NULL-Verschlüsselung ist nie zulässig.

    Dieser Wert unterstützt die SSL 3.0- und TLS 1.0-Protokolle sowie alle auf dem System installierten Verschlüsselungsverfahren mit Ausnahme der NULL-Verschlüsselung.

  • SslAllowNullEncryption – Ein Socket, der SSL/TLS zur Verschlüsselung bevorzugt. Bei diesem Wert wird die Verwendung der vollständigen Verschlüsselung bevorzugt. Eine NULL-Verschlüsselung (keine Verschlüsselung) ist jedoch je nach Serverkonfiguration zulässig.

  • BluetoothEncryptionAllowNullAuthentication – Ein Bluetooth-Socket, der die Verwendung einer Verschlüsselung bevorzugt, je nach Konfiguration des Zielservers aber eine NULL-Verschlüsselung (keine Verschlüsselung) zulässt.

  • BluetoothEncryptionWithAuthentication – Ein Bluetooth-Socket, der eine Verschlüsselung verwenden muss. Dieser Wert erfordert eine Verschlüsselung, und eine NULL-Verschlüsselung ist nie zulässig.

  • Ssl3AllowWeakEncryption – Ein TCP-Socket, der SSL zur Verschlüsselung verwenden muss. Dieser Wert unterstützt das SSL 3.0-Protokoll sowie alle auf dem System installierten Verschlüsselungsverfahren mit Ausnahme der NULL-Verschlüsselung. Dieser Wert lässt RC4 und andere schwache Verschlüsselungen zu, die als unsicher gelten.

  • Tls10 – Ein TCP-Socket, der SSL zur Verschlüsselung verwenden muss. Dieser Wert unterstützt das TLS 1.0-Protokoll sowie alle auf dem System installierten Verschlüsselungsverfahren mit Ausnahme von RC4, anderer schwacher Verschlüsselungen und der NULL-Verschlüsselung.

  • Tls11 – Ein TCP-Socket, der SSL zur Verschlüsselung verwenden muss. Dieser Wert unterstützt die TLS 1.1- und TLS 1.0-Protokolle sowie alle auf dem System installierten Verschlüsselungsverfahren mit Ausnahme von RC4, anderer schwacher Verschlüsselungen und der NULL-Verschlüsselung.

  • Tls12 – Ein TCP-Socket, der SSL zur Verschlüsselung verwenden muss. Dieser Wert unterstützt die TLS 1.2-, TLS 1.1- und TLS 1.0-Protokolle sowie alle auf dem System installierten Verschlüsselungsverfahren mit Ausnahme von RC4, anderer schwacher Verschlüsselungen und der NULL-Verschlüsselung.

In der Regel wird der Wert SslAllowNullEncryption verwendet. Er lässt die NULL-Verschlüsselung zu, d. h. keine Verschlüsselung. Die Netzwerkkommunikation wird somit u. U. nicht verschlüsselt. Der Wert SslAllowNullEncryption lässt nicht zu, dass der Server bei der SSL/TSL-Aushandlung anhand des digitalen Zertifikats und der Zertifizierungsstelle überprüft wird.

Die tatsächlich mit ConnectAsync oder UpgradeToSslAsync ausgehandelte SSL-Verschlüsselungsstärke kann durch Abrufen der StreamSocketinformation.ProtectionLevel-Eigenschaft ermittelt werden.

Verwandte Themen

Sonstige

Verbinden mit Sockets

So wird's gemacht: Herstellen einer Verbindung mit einem Datagrammsocket

So wird's gemacht: Herstellen einer Verbindung mit einem Streamsocket

So wird's gemacht: Verwenden erweiterter Socketsteuerelemente

Referenz

SocketProtectionLevel

StreamSocket

StreamSocket.ConnectAsync

StreamSocket.UpgradeToSslAsync

StreamSocketinformation.ProtectionLevel

Windows.Networking.Sockets

Beispiele

StreamSocket-Beispiel