TLS 1.2에서 핸드 쉐이크는 어떻게 동작할까?

uncle.ra·2023년 9월 11일
post-thumbnail

들어가기 전에

HTTP와 관련해서 공부하다 보면 당연하게도 HTTPS, TLS, SSL 등의 용어가 등장한다. Client와 Server가 데이터를 주고 받을 때 데이터를 암호화해서 전달하기 때문에 안전하다 정도로 알고 있었는데, 어떻게 동작하는 걸까?🤔
실제로 통신을 어떻게 주고 받는지 Wireshark 프로그램을 이용해서 확인한 내용을 포함해 정리해 보려고 한다.

들어가기 전에 알면 좋은 내용들

대칭 키(Symmetric Key)

Client와 Server가 동일한 키(=대칭키)를 가지고 있어서 Data를 암호화 및 복호화가 둘 다 가능한 키를 대칭키라고 한다. 대칭키를 사용했을 때 장점은 빠르게 암호화 및 복호화가 가능하다는 점이다. 반면에 대칭키를 사용했을 때 단점은 탈취를 당했을 때 바로 보안상의 위협으로 다가온다.

비대칭 키(Asymmetric Key)

비대칭 키는 A키를 이용해서 암호화를 한다면 B키를 이용해서만 복호화가 가능하고, B키를 이용해서 암호화를 한다면 A키를 이용해서만 복호화가 가능한 키를 말한다.

일반적으로 Server에서 Private Key를 보관하고 Client에는 탈취를 당해도 문제가 없는 Public Key를 전달하게 된다. 유일하게 복호화가 가능한 키는 서버에서 가지고 있는 Private Key뿐이기 때문이다. 따라서 Public Key를 탈취 당하더라도 안전하다는 장점이 존재한다. 반면애 암호화 및 복호화 작업이 대칭 키에 비해 상당히 느리다는 단점이 있다.

위에서 언급한 대칭/비대칭 키의 장/단점 때문에
대칭/비대칭 키를 혼합해서 TLS Handshake를 수행한다.

TLS Handshake란?

SSL? TLS? 어떤 용어일까?

SSL(Secure Sockets Layer)과 TLS(Transport Layer Security)는
Client, Server간의 데이터를 암호화하는 통신 프로토콜을 의미한다.

여기서 TLS, SSL은 사실상 의미하는 바는 동일하다.
SSL은 3.0 Version 이후 부터 TLS로 명칭이 변경이 되어 사용되고 있다!

Handshake?

handshake

Handshake의 사전적 의미를 찾아보면 '악수' 라고 나온다.
철수와 영희는 만났을 때 처음에 '악수'를 무조건 적으로 하진 않겠지만 '인사'를 하게 된다. '악수' 혹은 '인사'를 하게 되면 서로의 성별, 외모, 키 등의 정보 얻을 수 있다.

컴퓨터 세계에서도 마찬가지이다! Client와 Server는 서로 통신을 하려고 할 때
Handshake(정말 이 용어를 사용한다.) 과정을 거치고 나서야 데이터를 주고 받게 된다.

TLS Handshake는?

TLS Handshake를 정의하기 이전에, 이 과정이 필요한 이유가 뭔지를 우선 생각해 보면 좋을 것 같다.

"암호화 방식을 결정한다", "서로 검증한다" 와 같은 말을 먼저 읽게 되면 이해가 안될 것이다. (나 역시도 이해하느라 많은 시간을 썼다..)

결국 TLS Handshake를 통해 얻고자 하는 것은,
Client와 Server가 주고 받을 데이터를 암호화 및 복호화를 할 수 있는 대칭키를 얻고자 함이다.

서로 데이터를 암호화할 수 있는 대칭키를 얻기 위해서 TLS Handshake 과정을 필요로 하게 되었고 이 과정 속에서는 총 4가지를 수행하게 된다.

  1. Client와 Server가 서로 사용할 TLS 버전을 지정한다.
  2. Client와 Server가 서로 사용할 암호화 방식을 결정한다.
  3. Client와 Server는 서로를 검증한다.
  4. TLS Handshake가 완료된 이후에 Session Key를 생성한다(=Session ID).

어떻게 동작하는지 자세히 살펴보자🕵️‍

아래의 이미지가 필자가 느꼈을 때 제일 이해가 되어서 가져와 봤다.

tls-handshake-flow

출처: Cloudflare

전체 순서는 아래와 같다.

  1. 3-way-handshake(TCP)
  2. Client Hello
  3. Server Hello, Certificate, ServerHelloDone
  4. ClientKeyExchange, ChangeCipherSpec, Finished
  5. ChangeCipherSpec, Finished

0. 3-way-handshake(TCP)

이런 말을 들어본 적 있을 것이다.

HTTP는 TCP기반 프로토콜이기 때문에 신뢰성이 보장되며 UDP기반 프로토콜에 비해 처리 속도는 느리지만 안전하다

HTTP는 TCP 기반으로 통신을 하기 때문에 wireShark를 통해 확인해 보면

3-way-handshake-in-wireshark

Client와 Server가 통신을 하려고 할 때 데이터를 3번 주고 받는 것을 알 수 있다.

  1. Client -> Server: SYN
  2. Server -> Client: SYN, ACK
  3. Client -> Server: ACK

3-way-handshake를 통해 Client와 Server는 서로 연결되었음을 확인한다.

1. ClientHello

여기서 부터 TLS Handshake로 생각하면 된다.

ClientHello-in-wireshark

3-way-handshake를 통해 서로 연결이 되고난 직후에 Client는 Server에게
ClientHello와 관련된 패킷을 보낸다. 이 패킷은 아래의 내용을 담아서 전달 된다.

ClientHello-in-wireshark detail

  1. Version: Client에서 지원하는 TLS Version
  2. Random: Client에서 생성한 랜덤 데이터 -> 인증서 검증 이후 대칭키를 만들 때 사용
  3. Session ID: Client, Server간 최초로 TLS Handshake를 시도한 이후 부터는 Session ID를 이용해서 통신을 주고 받는다.
  4. Cipher Suites: Client에서 지원하는 암호화 방식들
    (위에 이미지에서는 총 16가지의 암호화 방식을 지원한다.)

2. ServerHello, Certificate, ServerHelloDone

2-1. ServerHello

Client의 사전 정보들을 받은 Server는 ServerHello 패킷을 Client에게 전송한다. 이 때, 아래의 정보를 전송한다.

  1. Version: Server에서 Client에서 지원하는 TLS Version 중 하나를 Server에서 선택
  2. Random: Server에서 생성한 랜덤 데이터 -> 인증서 검증 이후 대칭키를 만들 때 사용
  3. Session ID: Client, Server간 최초로 TLS Handshake를 시도한 이후 부터는 Session ID를 이용해서 통신을 주고 받는다.
  4. Cypher Suite: Client에서 지원하는 암호화 방식들 중 하나를 Server에서 선택

2-2. Certificate

certificate-in-wireshark

Server에서는 ServerHello 패킷을 전송하자마자 Certificate 패킷도 같이 전송을 한다.

Certificate 패킷 안에는 이름에서 유추할 수 있듯 암호화 되어 있는 인증서 정보가 들어가 있다.

여기서 잠깐! 암호화가 되어 있다고 했는데 여기서 말하는 암호화는 뭘까?
처음 인증서를 발급 받게 될 때, CA(Certificate Authority) 공인 기관에서 받게 되는데, 이 때 Private Key로 암호화 된 인증서를 발급 받게 된다.

그러면 이걸 어떻게 복호화 할 수 있을까?
브라우저에는 CA 공인 기관에 대한 정보 + 각 기관의 Public Key에 대한 정보를 가지고 있다. 해당 공인 기관에 대한 정보를 조회한 이후에 Public Key를 이용해 인증서를 복호화 할 수 있다.

이때 인증서 정보에는 서버에 대한 다양한 정보들이 들어있는데, 그 중에서 TLS Handshake 과정 중에 중요한 구성요소는 아래와 같다.

  1. Signature, 유효 기간
    CA 공인 기관에 포함되어 있지 않은 기관이거나 유효 기간이 지난 인증서 이거나 Signature가 위조된 경우 등에서는 검증에 실패하게 된다.
  1. 공개 키
    검증을 성공한 이후에 대칭키를 서버에 전달할 때 해당 공개 키를 통해 암호화한 이후에 전달하게 된다.

2-3 ServerHelloDone

server-hello-done-in-wireshark

단순하게 "ServerHello Packet 전달을 완료했다"의 의미로 전달한다고 생각하면 된다.

5. ClientKeyExchange, ChangeCypherSpec, Finished

client-key-exchange-in-wireshark

5-1. ClientKeyExchange

인증서를 통해 검증이 완료된 이후에,
1. ClientHello, ServerHello 과정에서 주고 받았던 Random 데이터를 조합해서 대칭키를 생성한다.
2. 그리고 복호화된 인증서에 들어있는 Public Key를 이용해서 암호화 한다.
3. ClientKeyExchange 패킷을 전송한다.

5-2. ChangeCypherSpec

"Client는 이후부터 전송되는 패킷은 암호화해서 보내겠다"는 의미로 전달한다고 생각하면 된다.

5-3. Finished

"TLS-Handshake Client쪽은 마무리 했다"는 의미로 전달한다고 생각하면 된다.

6. ChangeCypherSpec, Finished

ChangeCypherSpec-in-wireshark

6-1 ChangeCypherSpec

"Server는 이후부터 전송되는 패킷은 암호화해서 보내겠다"는 의미로 전달한다고 생각하면 된다.

6-2 Finished

"TLS-Handshake Server쪽도 마무리 했다"는 의미로 전달한다고 생각하면 된다.

마무리

글을 최대한 정리하며 쓰려고 했는데, 작성하고 보니 많이 길어진 것 같다🤔

결국 이 글에서의 가장 중요한 부분은 Client와 Server간의 데이터를 주고 받을 때 암호화 및 복호화를 할 수 있는 대칭키를 얻기 위해서 TLS Handshake를 수행한다. 는 부분이라고 생각한다.

또 2018년에는 TLS 1.3버전이 출시되었다. TLS 1.2 버전 보다 보안, 속도 적인 부분에서 월등히 뛰어난 버전으로 알고 있다. 해당 부분에 대해서도 공부한 이후에 글을 작성하면 좋을 것 같다🧐

참조

0개의 댓글