Idioma: HTML | XAML

Como proteger conexões de soquete com TLS/SSL (XAML)

Applies to Windows and Windows Phone

Este tópico mostra como proteger conexões de soquete de fluxo com TLS/SSL ao usar um StreamSocket em um aplicativo do Tempo de Execução do Windows.

O que você precisa saber

Tecnologias

Pré-requisitos

  • Os exemplos a seguir neste tópico são fornecidos em C# e C++. Um entendimento básico de soquetes e do uso de SSL/TLS é recomendado.

Visão geral de uma conexão SSL/TLS

SSL e o mais recente TLS são protocolos criptográficos desenvolvidos para fornecer autenticação e criptografia para comunicações por rede. Esses protocolos foram desenvolvidos para impedir a interceptação e a manipulação de dados enviados ou recebidos pela rede. Esses protocolos usam um modelo cliente-servidor para as trocas de protocolos. Esses protocolos também usam certificados digitais e autoridades de certificação para verificar se o servidor é quem diz ser. O protocolo TLS está documentado na RFC 5246 da IETF. O protocolo SSL, mais antigo, foi documentado pela Netscape Communications. O SSL costuma ser usado para fazer referência a esses dois protocolos.

O objeto StreamSocket pode ser configurado para usar SSL/TLS para comunicação entre o cliente e o servidor. Esse suporte a SSL/TLS é limitado ao uso do objeto StreamSocket como o cliente na negociação SSL/TLS. Atualmente, o SSL/TLS não pode ser usado pelo StreamSocketListener com o StreamSocket criado quando uma conexão é recebida para habilitar SSL/TLS no StreamSocket criado, já que a negociação SSL/TLS como servidor não foi implementada para um StreamSocket. O suporte de cliente para SSL/TLS não inclui a capacidade de usar certificados de cliente.

Há duas maneiras de proteger uma conexão StreamSocket com SSL/TLS:

  • ConnectAsync - Estabeleça a conexão inicial com um serviço de rede e negocie imediatamente para usar SSL/TLS em todas as comunicações.
  • UpgradeToSslAsync - Conecte-se, inicialmente, a um serviço de rede sem criptografia. O aplicativo pode enviar ou receber dados. Feito isso, atualize a conexão para usar SSL/TLS em toda a comunicação adicional.

Usar ConnectAsync

Estabelece a conexão inicial com um serviço de rede e negocia imediatamente para usar SSL/TLS em todas as comunicações. Há dois métodos ConnectAsync que oferecem suporte para a passagem de um parâmetro protectionLevel:

Se o parâmetro protectionLevel estiver definido como Windows.Networking.Sockets.SocketProtectionLevel.Ssl ao chamar um dos métodos ConnectAsync acima, o StreamSocket deverá usar SSL/TLS para criptografia.. Esse valor requer criptografia e jamais permite que uma criptografia NULA seja usada.

A sequência de uso normal de um desses métodos ConnectAsync é a mesma.

  • Crie um StreamSocket.
  • Caso seja necessária uma opção avançada no soquete, use a propriedade StreamSocket.Control para obter a instância de StreamSocketControl associada a um objeto StreamSocket. Defina uma propriedade no StreamSocketControl.
  • Chame um dos métodos ConnectAsync acima para iniciar uma operação de conexão com um destino remoto e começar imediatamente a negociação do uso do SSL/TLS.

O exemplo a seguir cria um StreamSocket e tenta estabelecer uma conexão com o serviço de rede e negociar imediatamente o uso do SSL/TLS. Se a negociação for bem-sucedida, toda comunicação da rede que usar o StreamSocket entre o cliente e o servidor da rede será criptografada.



using Windows.Networking;
using Windows.Networking.Sockets;


    // Define some variables and set values
    StreamSocket clientSocket = new StreamSocket();
 
    HostName serverHost = new HostName("www.contoso.com");
    string serverServiceName = "https";

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

    // Try to connect to contoso using HTTPS (port 443)
    try {

        // Call ConnectAsync method with SSL
        await clientSocket.ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel.Ssl);

        NotifyUser("Connected");
    }
    catch (Exception exception) {
        // If this is an unknown status it means that the error is fatal and retry will likely fail.
        if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
            throw;
        }

        NotifyUser("Connect failed with error: " + exception.Message);
        // Could retry the connection, but for this simple example
        // just close the socket.

        clientSocket.Dispose();
        clientSocket = null; 
    }
       
    // Add code to send and receive data using the clientSocket
    // and then close the clientSocket



Usar UpgradeToSslAsync

Estabelece uma conexão inicial com um serviço de rede sem criptografia. O aplicativo pode enviar ou receber alguns dados e, então, atualizar a conexão para o uso de SSL/TLS em todas as comunicações posteriores. Isso emprega o seguinte método:

O método UpgradeToSslAsync aceita dois parâmetros. O parâmetro protectionLevel indica o nível de proteção desejado. O parâmetro validationHostName é o nome do host do destino remoto de rede usado para validação durante a atualização para SSL. Normalmente, o validationHostName seria o mesmo nome de host usado pelo aplicativo para estabelecer a conexão inicialmente. Se o parâmetro protectionLevel estiver definido como Windows.System.Socket.SocketProtectionLevel.Ssl ao chamar o método UpgradeToSslAsync acima, o StreamSocket deverá usar SSL/TLS para criptografia. Esse valor requer criptografia e jamais permite que uma criptografia NULA seja usada.

A sequência normal de uso com o método UpgradeToSslAsync é a seguinte:

  • Crie um StreamSocket.
  • Caso seja necessária uma opção avançada no soquete, use a propriedade StreamSocket.Control para obter a instância de StreamSocketControl associada a um objeto StreamSocket. Defina uma propriedade no StreamSocketControl.
  • Caso seja necessário enviar e receber dados sem criptografia, envie-os agora.
  • Chame o método UpgradeToSslAsync para iniciar uma operação de atualização da conexão para usar SSL/TLS.

O exemplo a seguir cria um StreamSocket, tenta estabelecer uma conexão com o serviço de rede, envia alguns dados iniciais e depois negocia o uso de SSL/TLS. Se a negociação for bem-sucedida, toda comunicação da rede que usar o StreamSocket entre o cliente e o servidor da rede será criptografada.



using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

    // Define some variables and set values
    StreamSocket clientSocket = new StreamSocket();
 
    HostName serverHost = new HostName("www.contoso.com");
    string serverServiceName = "http";

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

    // Try to connect to contoso using HTTP (port 80)
    try {
        // Call ConnectAsync method with a plain socket
        await clientSocket.ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel.PlainSocket);

        NotifyUser("Connected");

    }
    catch (Exception exception) {
        // If this is an unknown status it means that the error is fatal and retry will likely fail.
        if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
            throw;
        }

        NotifyUser("Connect failed with error: " + exception.Message, NotifyType.ErrorMessage);
        // Could retry the connection, but for this simple example
        // just close the socket.

        clientSocket.Dispose();
        clientSocket = null; 
        return;
    }

    // Now try to sent some data
    DataWriter writer = new DataWriter(clientSocket.OutputStream);
    string hello = "Hello World ☺ ";
    Int32 len = (int) writer.MeasureString(hello); // Gets the UTF-8 string length.
    writer.WriteInt32(len);
    writer.WriteString(hello);
    NotifyUser("Client: sending hello");

    try {
        // Call StoreAsync method to store the hello message
        await writer.StoreAsync();

        NotifyUser("Client: sent data");

        writer.DetachStream(); // Detach stream, if not, DataWriter destructor will close it.
    }
    catch (Exception exception) {
        NotifyUser("Store failed with error: " + exception.Message);
        // Could retry the store, but for this simple example
            // just close the socket.

            clientSocket.Dispose();
            clientSocket = null; 
            return;
    }

    // Now upgrade the client to use SSL
    try {
        // Try to upgrade to SSL
        await clientSocket.UpgradeToSslAsync(SocketProtectionLevel.Ssl, serverHost);

        NotifyUser("Client: upgrade to SSL completed");
           
        // Add code to send and receive data 
        // The close clientSocket when done
    }
    catch (Exception exception) {
        // If this is an unknown status it means that the error is fatal and retry will likely fail.
        if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
            throw;
        }

        NotifyUser("Upgrade to SSL failed with error: " + exception.Message);

        clientSocket.Dispose();
        clientSocket = null; 
        return;
    }
    


Comentários

A enumeração SocketProtectionLevel possui três valores possíveis:

  • PlainSocket - Um soquete simples sem criptografia.
  • Ssl - Um soquete que deve usar SSL/TLS para criptografia. Esse valor requer criptografia e jamais permite uma criptografia NULA.

    Esse valor oferece suporte aos protocolos SSL 3.0 e TLS 1.0 e a todas as criptografias instaladas no sistema, exceto a criptografia NULA.

  • SslAllowNullEncryption - Um soquete que prefere usar SSL/TLS para criptografia. Esse valor dá preferência ao uso de criptografia completa, mas permite uma criptografia NULA (sem criptografia) com base na configuração do servidor.
  • BluetoothEncryptionAllowNullAuthentication – Um soquete Bluetooth que prefere que a criptografia seja utilizada, mas permite uma criptografia NULA (sem criptografia) com base na configuração do servidor de destino.
  • BluetoothEncryptionWithAuthentication – Um soquete Bluetooth que deve usar criptografia. Esse valor requer criptografia e jamais permite uma criptografia NULA.
  • Ssl3AllowWeakEncryption – Um soquete TCP que deve usar SSL para criptografia. Esse valor oferece suporte ao protocolo SSL 3.0 e todas as criptografias instaladas no sistema, exceto a criptografia NULA. Este valor permite RC4 e outras criptografias fracas que são consideradas inseguras.
  • Tls10 – Um soquete TCP que deve usar SSL para criptografia. Esse valor oferece suporte ao protocolo TLS 1.0 e a todas as criptografias instaladas no sistema, exceto RC4, outras criptografias fracas e a criptografia NULA.
  • Tls11 – Um soquete TCP que deve usar SSL para criptografia. Esse valor oferece suporte ao protocolo TLS 1.1 e TLS 1.0 e a todas as criptografias instaladas no sistema, exceto RC4, outras criptografias fracas e a criptografia NULA.
  • Tls12 – Um soquete TCP que deve usar SSL para criptografia. Esse valor oferece suporte aos protocolos TLS 1.2, TLS 1.1 e TLS 1.0 e a todas as criptografias instaladas no sistema, exceto RC4, outras criptografias fracas e a criptografia NULA.

O valor SslAllowNullEncryption normalmente não é usado, pois permite o uso de uma criptografia NULA (que representa ausência de criptografia) e, portanto, a comunicação de rede talvez não seja criptografada. O valor SslAllowNullEncryption permite que a negociação SSL/TLS valide o servidor com base no certificado digital desse servidor e na autoridade de certificação.

O nível de segurança do SSL negociado usando ConnectAsync ou UpgradeToSslAsync poderá ser determinado com a obtenção da propriedade StreamSocketinformation.ProtectionLevel.

Tópicos relacionados

Outro
Conectando-se com soquetes
Como se conectar com um soquete de fluxo
Como usar controles de soquete avançados
Referência
SocketProtectionLevel
StreamSocket
StreamSocket.ConnectAsync
StreamSocket.UpgradeToSslAsync
StreamSocketinformation.ProtectionLevel
Windows.Networking.Sockets

 

 

Mostrar:
© 2014 Microsoft