[转]如何借助 TLS/SSL 确保套接字连接的安(使用 C#/VB/C++ 和 XAML 的 Windows 应用企业应用)

正文转自:http://msdn.microsoft.com/zh-cn/library/windows/apps/jj150597.aspx

按主题将显示在运用 StreamSocket 功能时,如何如 Windows
应用企业应用可以保护 TLS/SSL 流套接字连接。

您要了解的情节

技术

  • Windows.Networking.Sockets

    采取模拟接字和 WebSocket 启用网络通信。

先决条件

  • 每当比如主题中,以下示例都来源于 C# 和 C++。建议对法接字和 SSL/TLS
    的施用产生一个为主的问询。

SSL/TLS 连接概述

平安法接字层 (SSL) 和时的传层安全 (TLS)
都是旨在为网络通信提供身份验证和加密功能的加密协议。这些协议专门用于在殡葬和收取网络数据经常防备发生窃听与歪曲。
这些协议利用同样种客户端-服务器模型进行商榷交换。这些协议还见面使数字证书和证书颁发机构来证实服务器是否跟该自称的身价相符。TLS
商谈记录在 IETF RFC
5246 中。 早期的 SSL 协议由 Netscape
Communications 记录。 SSL 通常用于因及时有限种植协议。

StreamSocket 对象好配备用于在客户端和服务器之间使用
SSL/TLS 进行通信。对 SSL/TLS 的支撑但限于在 SSL/TLS 协商中将 StreamSocket 对象用作客户端。当系统接受一个一连为当为创造的 StreamSocket 上启用 SSL/TLS
时,由于当服务器的 SSL/TLS 协商无呢 StreamSocket 实现,所以StreamSocketListener 现在匪克动用 SSL/TLS
用于受创造的 StreamSocket。 SSL/TLS
的客户端支持非包运用客户端证书的作用。

来以下简单种植办法好借助 SSL/TLS 确保 StreamSocket 连接的安康:

 

  • ConnectAsync –
    建立到网络服务的开始连接并当即商讨对负有通信使用 SSL/TLS。
  • UpgradeToSslAsync –
    先不加密连接至网络服务。应用得发送或接收数据。然后升级总是,对以后享有通信使用
    SSL/TLS。

使用 ConnectAsync

树立与网络服务的开连接并立即商讨对富有通信使用 SSL/TLS。有点儿种植 ConnectAsync 方法支持传递protectionLevel 参数:

 

  • ConnectAsync(EndpointPair,
    SocketProtectionLevel)
     – 在 StreamSocket 对象上启动异步操作以连续至EndpointPair 对象和 SocketProtectionLevel 所指定的远程网络目标。
  • ConnectAsync(HostName, String,
    SocketProtectionLevel)
     – 在 StreamSocket 对象上启动异步操作为连续至由长途主机名、远程服务名和 SocketProtectionLevel 所指定的远程目标。

如果 protectionLevel 参数为装置为 Windows.Networking.Sockets.SocketProtectionLevel.Ssl,当调用上述任一ConnectAsync 方法时,StreamSocket 必须使用 SSL/TLS
用于加密。此值需要加密而且绝不允许使用 NULL 密码。

一般的话,使用这些 ConnectAsync 方法的相继都是一模一样的。

 

  • 创造一个 StreamSocket
  • 倘需要以模拟接字达利用高级选项,请用 StreamSocket.Control 属性获取和 StreamSocket 对象
    相关联的StreamSocketControl 实例。 针对 StreamSocketControl 设置一个性。
  • 调用上述 ConnectAsync 方法之一为启动连接到远程目标的操作,并随即商讨下
    SSL/TLS。

以下示例将会创造 StreamSocket,并尝试建立和网络服务的接连并立刻商讨下
SSL/TLS。如果协议成功,则当客户端和网络服务器之间以 StreamSocket 的有着网络通信都以给加密。

C#

C++

 

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

使用 UpgradeToSslAsync

预先不加密建立和网络服务的开端连接。应用得发送或接收数据。然后升级总是,对下具备通信使用
SSL/TLS。使用如下方法:

 

  • UpgradeToSslAsync –
    启动一个异步操作以升级至在 StreamSocket 对象上应用 SSL。

UpgradeToSslAsync 方法有三三两两独参数。protectionLevel 参数表示所用的护卫级别。validationHostName 参数是于晋级至 SSL
时用于进行求证的远距离网络目标的主机名。
通常状态下,validationHostName 将是运用初期建立连接时所用的同样主机名。如果 protectionLevel 参数为安装为 Windows.System.Socket.SocketProtectionLevel.Ssl,当调用上述任一 UpgradeToSslAsync 方法时,StreamSocket 必须采用 SSL/TLS
用于加密。此值需要加密而且绝不允许使用 NULL 密码。

相似的话,使用 UpgradeToSslAsync 方法的一一都是:

 

  • 创一个 StreamSocket
  • 如若欲以法接字达以高级选项,请动 StreamSocket.Control 属性获取与 StreamSocket 对象
    相关联的StreamSocketControl 实例。 针对 StreamSocketControl 设置一个特性。
  • 假设其他数要为非加密的款式开展发送和接受,则随即发送。
  • 调用 UpgradeToSslAsync 方法以启动以接连升级为下
    SSL/TLS。

以下示例将会见创 StreamSocket,并尝试成立及网络服务的连天、发送一些从头数据,然后协商下
SSL/TLS。如果协议成功,则当客户端和网络服务器内用 StreamSocket 的兼具网络通信都以被加密。

C#

C++

 

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;
    }

备注

SocketProtectionLevel 枚举 有三只或的值:

 

  • PlainSocket –
    一个未加密的纯套接字。
  • Ssl – 一个不能不下
    SSL/TLS 进行加密的套接字。此值需要加密而且绝不允许使用 NULL 密码。
  • SslAllowNullEncryption – 一个首选使用 SSL/TLS
    进行加密的套接字。该值首选使用了加密,但允许基于服务器的配置使用
    NULL 密码(即未加密)。

常见不使 SslAllowNullEncryption 值,因为她同意采取 NULL
密码,这即代表不加密,所以网络通信可能也未加密。SslAllowNullEncryption 值允许 SSL/TLS
协商,以根据服务器数字证书和证件颁发机构针对服务器进行验证。

倘运用 SslAllowNullEncryption 值,那么实际上采取 ConnectAsync 或 UpgradeToSslAsync 协商得到的 SSL 强度可通过获得 StreamSocketinformation.ProtectionLevel 属性来规定。

连带主题

其他

以模拟接字进行连接

使模拟接字进行连续(使用 JavaScript 和 HTML 的 Windows
应用商店应用)

怎借助 TLS/SSL 确保套接字连接的安全(使用 JavaScript 和 HTML 的
Windows
应用企业应用)

何以使高级套接字控件

飞入门:使用流套接字进行连续

参考

SocketProtectionLevel

StreamSocket

StreamSocket.ConnectAsync

StreamSocket.UpgradeToSslAsync

StreamSocketinformation.ProtectionLevel

Windows.Networking.Sockets