다음을 통해 공유


TLS/SSL을 통해 소켓 연결의 보안을 유지하는 방법(HTML)

[ 이 문서는 Windows 런타임 앱을 작성하는 Windows에서 8.x 및 Windows Phone 8.x 개발자를 대상으로 합니다. Windows 10용으로 개발하는 경우에는 최신 설명서를 참조하세요.]

이 항목에서는 Windows 스토어 앱에서 StreamSocket 기능을 사용할 경우 TLS/SSL을 통해 스트림 소켓 연결의 보안을 유지하는 방법을 보여 줍니다.

알아야 할 사항

기술

사전 요구 사항

  • 이 항목의 다음 예제는 JavaScript로 제공됩니다. 소켓 및 SSL/TLS 사용에 대해 기본적으로 이해하고 있는 것이 좋습니다.

SSL/TLS 연결 개요

SSL(Secure Sockets Layer) 및 더 최근의 TLS(전송 계층 보안)는 네트워크 통신에 인증 및 암호화를 제공하도록 설계된 암호화 프로토콜입니다. 이러한 프로토콜은 네트워크 데이터를 보내고 받을 때 도청 및 변조를 방지하도록 설계되었습니다. 이러한 프로토콜은 프로토콜 교환에 클라이언트-서버 모델을 사용합니다. 이러한 프로토콜은 또한 디지털 인증서 및 인증 기관을 사용하여 서버가 인증이 필요한 개체인지 확인합니다. TLS 프로토콜에 대해서는 IETF RFC 5246에 설명되어 있습니다. 이전의 SSL 프로토콜은 Netscape Communications의 문서에 기록되어 있습니다. SSL은 일반적으로 이러한 프로토콜을 모두 나타내는 데 사용됩니다.

클라이언트와 서버 간 통신에 SSL/TLS를 사용하도록 StreamSocket 개체를 구성할 수 있습니다. SSL/TLS에 대한 이 지원은 클라이언트가 SSL/TLS 협상 중일 때 StreamSocket 개체를 사용하는 것으로 제한됩니다. 서버로서의 SSL/TLS 협상이 StreamSocket에 대해 구현되어 있지 않으므로 연결을 받을 때 StreamSocket이 생성되는 StreamSocketListener가 현재 SSL/TLS를 통해 StreamSocket에서 SSL/TLS를 사용하도록 설정할 수 없습니다. SSL/TLS에 대한 클라이언트 지원에 클라이언트 인증서를 사용하는 기능은 포함되지 않습니다.

SSL/TLS를 통해 StreamSocket 연결의 보안을 유지하는 방법은 다음 두 가지입니다.

  • ConnectAsync - 네트워크 서비스에 대한 초기 연결을 설정하고 모든 통신에 SSL/TLS를 사용하도록 즉시 협상합니다.
  • UpgradeToSslAsync - 처음에 암호화 없이 네트워크 서비스에 연결합니다. 앱은 데이터를 보내거나 받을 수 있습니다. 그런 다음 이후의 모든 통신에 SSL/TLS를 사용하도록 연결을 업그레이드합니다.

ConnectAsync 사용

네트워크 서비스에 대한 초기 연결을 설정한 다음 모든 통신에 SSL/TLS를 사용하도록 즉시 협상합니다. protectionLevel 매개 변수 전달을 지원하는 두 가지 ConnectAsync 메서드는 다음과 같습니다.

ConnectAsync 메서드 중 하나를 호출할 때 protectionLevel 매개 변수가 Windows.Networking.Sockets.SocketProtectionLevel.Ssl로 설정되어 있으면 StreamSocket은 암호화에 SSL/TLS를 사용해야 합니다. 이 값에는 암호화가 필요하고 NULL 암호를 사용할 수 없습니다.

이러한 ConnectAsync 메서드 중 하나에 사용할 일반적인 순서는 동일합니다.

  • StreamSocket을 만듭니다.
  • 소켓에 대한 고급 옵션이 필요하면 StreamSocket.Control 속성을 사용하여 StreamSocket 개체와 연결된 StreamSocketControl 인스턴스를 가져옵니다. StreamSocketControl에 대한 속성을 설정합니다.
  • ConnectAsync 메서드 중 하나를 호출하여 원격 대상에 연결하는 작업을 시작하고 SSL/TLS를 사용하도록 즉시 협상합니다.

다음 예제에서는 StreamSocket을 만들고 네트워크 서비스에 대한 연결을 시도한 다음 SSL/TLS를 사용하도록 즉시 협상합니다. 협상에 성공하면 클라이언트와 네트워크 서버 간에 StreamSocket을 사용하는 모든 네트워크 통신이 암호화됩니다.



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

UpgradeToSslAsync 사용

암호화하지 않고 네트워크 서비스에 대한 초기 연결을 설정합니다. 앱은 일부 데이터를 보내거나 받은 다음 이후의 모든 통신에 SSL/TLS를 사용하도록 연결을 업그레이드할 수 있습니다. 이때 다음 메서드를 사용합니다.

UpgradeToSslAsync 메서드는 두 개의 매개 변수를 사용합니다. protectionLevel 매개 변수는 원하는 보호 수준을 나타냅니다. validationHostName 매개 변수는 SSL로 업그레이드할 때 유효성 검사에 사용되는 원격 네트워크 대상의 호스트 이름입니다. 일반적으로 validationHostName은 앱이 처음에 연결을 설정하는 데 사용한 것과 같은 호스트 이름입니다. 위 UpgradeToSslAsync 메서드를 호출할 때 protectionLevel 매개 변수가 Windows.System.Socket.SocketProtectionLevel.Ssl로 설정되어 있으면 StreamSocket은 암호화에 SSL/TLS를 사용해야 합니다. 이 값에는 암호화가 필요하고 NULL 암호를 사용할 수 없습니다.

UpgradeToSslAsync 메서드에 사용하는 일반적인 순서는 다음과 같습니다.

  • StreamSocket을 만듭니다.
  • 소켓에 대한 고급 옵션이 필요하면 StreamSocket.Control 속성을 사용하여 StreamSocket 개체와 연결된 StreamSocketControl 인스턴스를 가져옵니다. StreamSocketControl에 대한 속성을 설정합니다.
  • 데이터를 암호화하지 않은 상태로 보내고 받아야 할 경우 지금 보냅니다.
  • UpgradeToSslAsync 메서드를 호출하여 작업을 시작하고 SSL/TLS를 사용하도록 연결을 업그레이드합니다.

다음 예제에서는 StreamSocket을 만들고 네트워크 서비스에 대한 연결을 시도한 후 일부 초기 데이터를 보내고 SSL/TLS를 사용하도록 협상합니다. 협상에 성공하면 클라이언트와 네트워크 서버 간에 StreamSocket을 사용하는 모든 네트워크 통신이 암호화됩니다.



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

설명

SocketProtectionLevel 열거형에는 다음과 같이 여러 가지 가능한 값이 있습니다.

  • PlainSocket - 암호화되지 않은 일반 소켓입니다.

  • Ssl - 암호화에 SSL/TLS를 사용해야 하는 소켓입니다. 이 값에는 암호화가 필요하고 NULL 암호를 허용하지 않습니다.

    이 값은 SSL 3.0 및 TLS 1.0 프로토콜과 시스템에 설치된 모든 암호화 암호(NULL 암호 제외)를 지원합니다.

  • SslAllowNullEncryption - 암호화에 기본적으로 SSL/TLS를 사용하는 소켓입니다. 이 값에는 기본적으로 전체 암호화가 사용되지만 서버 구성에 따라 NULL 암호(암호화 안 함)를 허용합니다.

  • BluetoothEncryptionAllowNullAuthentication - 기본적으로 해당 암호화를 사용하는 Bluetooth 소켓이지만 대상 서버의 구성에 따라 NULL 암호(암호화되지 않음)를 허용합니다.

  • BluetoothEncryptionWithAuthentication - 암호화를 사용해야 하는 Bluetooth 소켓입니다. 이 값에는 암호화가 필요하고 NULL 암호를 허용하지 않습니다.

  • Ssl3AllowWeakEncryption - 암호화에 SSL을 사용해야 하는 TCP 소켓입니다. 이 값은 SSL 3.0 프로토콜과 시스템에 설치된 모든 암호화 암호(NULL 암호 제외)를 지원합니다. 이 값은 RC4 및 기타 안전하지 않은 것으로 간주되는 약한 암호를 허용합니다.

  • Tls10 - 암호화에 SSL을 사용해야 하는 TCP 소켓입니다. 이 값은 TLS 1.0 프로토콜과 시스템에 설치된 모든 암호화 암호(RC4, 기타 약한 암호 및 NULL 암호 제외)를 지원합니다.

  • Tls11 - 암호화에 SSL을 사용해야 하는 TCP 소켓입니다. 이 값은 TLS 1.1 및 TLS 1.0 프로토콜과 시스템에 설치된 모든 암호화 암호(RC4, 기타 약한 암호 및 NULL 암호 제외)를 지원합니다.

  • Tls12 - 암호화에 SSL을 사용해야 하는 TCP 소켓입니다. 이 값은 TLS 1.2, TLS 1.1 및 TLS 1.0 프로토콜과 시스템에 설치된 모든 암호화 암호(RC4, 기타 약한 암호 및 NULL 암호 제외)를 지원합니다.

SslAllowNullEncryption 값은 NULL 암호를 사용하도록 허용하고 이는 암호화하지 않는 것을 의미하여 네트워크 통신이 암호화되지 않을 수 있으므로 이 값은 일반적으로 사용되지 않습니다. SslAllowNullEncryption 값은 서버 디지털 인증서 및 인증 기관을 기반으로 하여 SSL/TLS 협상에서 서버의 유효성을 검사하도록 허용합니다.

실제로 ConnectAsync 또는 UpgradeToSslAsync를 사용하여 협상된 SSL 수준은 StreamSocketinformation.ProtectionLevel 속성을 가져와서 결정할 수 있습니다.

관련 항목

기타

소켓을 사용하여 연결

데이터그램 소켓을 사용하여 연결하는 방법

스트림 소켓을 사용하여 연결하는 방법

고급 소켓 컨트롤을 사용하는 방법

참조

SocketProtectionLevel

StreamSocket

StreamSocket.ConnectAsync

StreamSocket.UpgradeToSslAsync

StreamSocketinformation.ProtectionLevel

Windows.Networking.Sockets

샘플

StreamSocket 샘플