SSL/TLS 톺아보기: 토..통신보안?

Heechan Kang·2일 전
1

HTTP 톺아보기

목록 보기
5/5

안녕하세요!
오늘은 이전에 다루었던 HTTP에 이어서 웹 보안의 중요한 축을 담당하는 SSL/TLS에 대해 조금 깊이있게 다루어보려고 합니다.

기술적인 내용을 다루기 때문에, 이해가 어려운 부분이 있을 수 있는데요, 이를 최대한 쉽게 설명하고자 노력하겠습니다.
혹시라도 틀린 부분이나, 궁금한 점이 있으시다면 언제든지 질문해 주세요!

개발자로 일하고 계신분들이라면 다들 SSL/TLS에 대해서 대략적으로는 알고 계실 것입니다.
요즘에는 HTTPS를 사용하지 않으면 어지간한 서비스는 불법이니까요.
그렇다면, SSL/TLS가 무엇인지, 어떻게 작동하는지, 왜 이것이 중요한지 알아보도록 하겠습니다.

SSL과 TLS: 이 두가지 이름은 무엇일까?

SSLTLS는 각각 Secure Socket LayerTransport Layer Security의 약자입니다.
둘다 뭐 비슷한 의미를 품고있고, 실제로 많은 경우에 이를 혼용하고있습니다.

이를 굳이 따져보자면 마치 호치키스스테이플러의 차이같다고 할 수 있습니다. 왜냐하면, SSL은 1990년대 중반에 넷스케이프에 의해 개발되었고, 이후 TLS로 발전하게 되었기 때문입니다.

TLS는 SSL 3.0을 기반으로 만들어졌지만, 더 높은 보안성과 성능을 제공합니다. 1999년 IETF(Internet Engineering Task Force)에 의해 표준화된 이후, TLS는 현재 인터넷 보안에서 표준으로 자리 잡고 있습니다. 그리고 현재는 TLS 1.3이 최신 버전으로 널리 사용되고 있습니다.

즉, SSL은 먼저 개발된 하나의 제품이고, TLS는 이것이 규격화된 하나의 표준 프로토콜이라고 할 수 있습니다.

성공한 제품 : 산업 표준
SSL : TLS
호치키스 : 스테이플러
포크레인 : 굴삭기

결론적으로, 엄밀히 따지면 현재 사용되는 것은 TLS이지만, SSL이라고 부르는 경우도 많습니다.

HTTPS, HTTP에 보안을 더한 것

다음으로 알아볼 것은, 이번 글의 본격적인 주제인 HTTPS입니다.
HTTPS는 HTTP(Hyper Text Transfer Protocol) + S(Secure)로, 다들 아시고 짐작하셨다 시피 HTTP에 보안을 더한 것입니다.

기존 HTTP는 데이터를 평문으로 전송하기 때문에, 중간에 누군가가 데이터를 가로채어 볼 수 있습니다. 이를 방지하기 위해, HTTPS는 데이터를 암호화하여 전송합니다. 이를 통해 중간에 누군가가 데이터를 가로채어도, 데이터를 해독할 수 없게 됩니다.

그렇다면 이러한 보안을 정확히 어떻게 구현하는 것일까요?

  • 영화 "윈드토커", 소수의 인디언만이 사용하는 언어를 암호 통신의 수단으로 사용하는 전쟁 영화

물론 이러한 암호 통신을 위한 방법은 수도없이 많습니다. 약속된 그들만의 언어를 사용할 수도 있고, 특정한 도서나 출판물을 사용한 약속을 통해 암호화를 할 수도 있습니다.
실제로 제 과거 경험을 예로 들어보자면, 군대에는 CEOI라는 것이 있습니다. 단순히 종이 한 장에 암호화 및 복호화를 위한 약속(키)가 쭈욱 적혀있을 뿐인데, 이것만으로도 암호화 통신을 할 수 있습니다.

가장 단순하고 쉬운 방법: 대칭키(Symmetric Key) 암호화

HTTPS에서 사용하는 방식도 이와 비슷합니다.
서버와 클라이언트가 특정한 키(대칭키)를 공유하고 이를 바탕으로 실제 통신에는 이 키를 사용해 해싱(암호화)된 데이터를 주고받습니다.
이를 통해 중간에 누군가가 데이터를 가로채어도, 키를 가지고있지 않다면 데이터를 해독할 수 없게 됩니다.

하지만 여기에는 한가지 큰 문제가 있습니다.

그런데.. 그 대칭키는 어떻게 안전하게 공유하지?

네 맞습니다. 대칭키는 양쪽이 동일한 키를 가지고 있어야 합니다. 그 키를 클라이언트가 만들건, 서버가 만들건, 필수적으로 이를 교환하는 과정이 필요합니다.
그런데 만에하나 이 키가 중간에 해커로부터 유출된다면 모든 통신은 노출되어버리게 됩니다.

남성분들은 아시겠지만, 이것이 군대에서 CEOI를 그렇게 소중하게 목에 걸고 다니는 이유이죠.
CEOI가 외부로 유출된다면, 조직 내의 모든 통신은 노출된다고 볼 수 있기 때문입니다.

참고 1) 암호화 방식의 첫 번째 축: 대칭키란 무엇일까?

⚠️ 앞으로 중간중간 몇 가지 참고사항이 있습니다.
이것들은 이해를 돕기 위한 것이니, 이미 잘 알고계시다면 넘어가셔도 무방합니다.

대칭키란, 암호화와 복호화에 동일한 키를 사용하는 방식입니다.
가장 널리 사용되는 대칭키 알고리즘으로는 AES(Advanced Encryption Standard)가 있습니다. AES는 빠르고 안전한 암호화 방식으로, 일반적으로 TLS 1.3에서는 128비트, 256비트의 키를 사용합니다.
이는 아래와 같은 방식으로 쉽게 사용 해 볼 수 있습니다.

여기서는 16바이트(128비트)의 키를 생성해보겠습니다.

openssl rand -hex 16
> 4353eed991856ca1730a2a6daaea9a5b

추가적으로 IV(Initialization Vector)라는 것도 있습니다.
이는 암호화를 할 때, 암호화된 데이터의 패턴을 무작위로 만들어주는 역할을 합니다. 이를 통해 같은 데이터를 암호화해도, 매번 다른 결과를 만들어내어 보안성을 높입니다.

openssl rand -hex 16
> 1402346b532b87618d6f7b247a2cd0ef

이제 암호화할 문자열을 생성해보겠습니다.

echo "Hello, I'm ford. nice to see you" > plaintext.txt

이제 암호화를 해보겠습니다.

openssl enc -aes-128-cbc -in plaintext.txt -out ciphertext.bin -K 4353eed991856ca1730a2a6daaea9a5b -iv 1402346b532b87618d6f7b247a2cd0ef

그러면 아래와 같은 파일이 생성됩니다.

// ciphertext.bin
�uQG@�qv,"�n4���+�",c ���L�PN��:S�^P�g�^w�

이제 복호화를 해보겠습니다.

openssl enc -d -aes-128-cbc -in ciphertext.bin -out decrypted.txt -K 4353eed991856ca1730a2a6daaea9a5b -iv 1402346b532b87618d6f7b247a2cd0ef

그러면 아래와 같은 파일이 생성됩니다.

// decrypted.txt
Hello, I'm ford. nice to see you

넵, 이렇게 정상적으로 복호화가 되었습니다. 이렇게 대칭키를 사용한 암호화 방식은 비교적 적은 연산량으로 빠르게 암호화를 할 수 있습니다.

그러면 이번에는 한 대칭키를 한번 한 글자만 틀려볼까요?

# key의 마지막 문자를 b 에서 a로 변경
openssl enc -d -aes-128-cbc -in ciphertext.bin -out decrypted-failed.txt -K 4353eed991856ca1730a2a6daaea9a5a -iv 1402346b532b87618d6f7b247a2cd0ef
> bad decrypt

결과물은 아래와 같습니다. 전혀 알아 볼 수 없죠? 복호화가 실패했기 때문입니다.

�v�*f�j�5ˇ�ȄM,d�ͩ�O&�ՒS|
참고 1-1) iv? 이건 또 뭐죠?

위의 암/복호화 과정에서 은근슬쩍 iv라는 항목이 사용되었습니다. 과연 이건 또 무엇일까요?

정말 단순하게 비유해서 설명하자면, iv(Initialization Vector)는 일종의 양념같은 존재입니다.
이를 통해 동일한 데이터를 암호화 하더라도 매번 다른 결과를 만들어내어 보안성을 높일 수 있게 해줍니다.

iv의 본질은 비밀보다는 매번 다른 결과를 만들어내는 것이기 때문에, 이 값은 암호화된 데이터와 함께 공개되어도 상관없습니다.
그래서 암호화된 데이터와 함께 전송되기도 합니다.

그렇다면 두 번째 방법: 비대칭키(Asymmetric Key) 암호화

첫번째 방법인 대칭키를 사용한 암호통신에서는 '대칭키를 어떻게 안전하게 공유할 것인가?'라는 문제가 있었습니다.
그렇다면 이 문제를 해결하기 위한 방법은 무엇일까요?
서로가 같은 키를 가지고 있지 않아도 통신을 할 수 있는 방법이 있을까요?
네, 그 방법이 바로 비대칭키 암호화입니다.

  • 편의상 여기서는 공개키를 P(빨간색)로, 개인키를 S(노란색)로 표현하겠습니다.

비대칭키 암호화는 두 개의 다른 키, 즉 공개키개인키를 사용합니다.
공개키로 암호화한 데이터는 개인키로만 복호화할 수 있으며, 반대로 개인키로 암호화한 데이터는 공개키로만 복호화할 수 있습니다.
후자의 경우는 특별히 전자서명이라고 부르기도 합니다.

위 도식과 같이, 이전과는 다르게 이번에는 자신의 공개키를 상대방에게 전달하고, 상대방은 이를 통해 데이터를 암호화하여 전달합니다.
그리고 이를 받은 자신은 개인키로 복호화하여 데이터를 확인합니다.

이렇게 하면, 제3자가 중간에 공개키와 데이터를 가로채더라도 이 데이터를 복호화할 수 있는 개인키를 가지고 있지 않기 때문에 데이터를 확인할 수 없게 됩니다.

만약 양방향 통신을 해야한다면 서로 공개키를 교환하여 통신을 할 수 있겠죠?
이로서 이전 대칭키를 사용하는 경우에 발생했던 문제점을 완전히 해결한것처럼 보입니다.

하지만 이 방법에도 한 가지 문제가 있습니다.
그것은 바로 성능입니다. 대칭키 암호화에 비해 비대칭키 암호화는 연산량이 많아서 느리다는 점이 큰 문제입니다. 이러한 이유로 우리는 이 문제를 해결하기 위해 또다른 방법을 사용합니다.

참고 2) 암호화 방식의 두 번째 축: 비대칭키란 무엇일까?

비대칭키란, 암호화와 복호화에 서로 다른 키를 사용하는 방식입니다.
가장 널리 사용되는 비대칭키 알고리즘으로는 RSA(Rivest-Shamir-Adleman)가 있습니다.
세 단어 모두 알고리즘의 개발자들의 이름을 따서 지어졌습니다. 읽기도 힘드네요.
RSA는 공개키 암호화 방식으로, 공개키로 암호화한 데이터는 개인키로만 복호화할 수 있으며, 반대로 개인키로 암호화한 데이터는 공개키로만 복호화할 수 있습니다.

RSA 암호화는 보통 2048비트, 4096비트의 키를 사용합니다. 이전에는 1024비트의 키를 사용하기도 했지만, 이제는 보안성이 떨어져 사용되지 않습니다.
여기서는 2048비트의 키를 생성해보겠습니다.

openssl genrsa -out private.pem 2048

이렇게 하면 Private Key가 생성됩니다. 생성된 키는 아래와 같이 생겼습니다.

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7EMlVx2Huqyno
...
...
L2/3i9pOV3bgD6ZStSvB4+U=
-----END PRIVATE KEY-----

이제 이 Private Key를 이용하여 Public Key를 생성해보겠습니다.

openssl rsa -in private.pem -pubout -out public.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuxDJVcdh7qsp6HNUX/LQ
...
...
TwIDAQAB
-----END PUBLIC KEY-----

딱 봐도 AES에 비하면 훨씬 길죠? 그만큼 연산량도 크고 무겁습니다. 그러면 이제 이 키를 이용하여 암호화를 해보겠습니다.

echo "Hello, I'm ford. nice to see you" > plaintext.txt
openssl pkeyutl -encrypt -inkey public.pem -pubin -in plaintext.txt -out ciphertext.bin

결과물은 이렇게 생겼습니다. 암호화가 잘 된 것을 확인할 수 있습니다.

�l��R�p�]o+N�xAo����bѽjd��.�Po���ԭ���z�� q�WS�a�P��M����.�^J�J�v<���'��H���Pf9�~	�g�?�]�6w75̱�d҆,�������N'��C����v#a/%{GqRo�/�m1�>7�/�J��0T��#���XC't�e]
7���������.�[`�Y
K��mxB�J�R��p%����H���i�^9��!�!����*]�K�*�=.�59���d

이제 복호화를 해보겠습니다.

openssl pkeyutl -decrypt -inkey private.pem -in ciphertext.bin -out decrypted.txt
Hello, I'm ford. nice to see you

그렇다면 이제 세 번째 방법: 공개키 + 대칭키 모두를 사용하자!

드디어 이제, 최종적으로 안전하게 통신하면서도 연산량을 낭비하지 않는 방법을 찾았습니다. 그 방법은 생각보다 간단합니다. 바로 공개키를 사용하여 대칭키를 암호화한 뒤 교환하는 것입니다. 이 방법으로 대칭키를 안전하게 교환하고, 이후에는 공유된 대칭키를 사용하여 데이터를 암호화하여 주고받습니다.

자, 여기까지의 과정은 생각보다 어렵지 않죠?
이제 이러한 개념을 바탕으로 본격적으로 HTTPS가 어떻게 작동하는지 알아보도록 하겠습니다.

참고 3) 암호화의 강도: 키 길이에 따른 보안 수준.

위의 AES와 RSA를 설명하는 부분에서 계속해서 AES-128, RSA-2048 등의 이름모를 숫자들이 등장했습니다.
이를 비도라고 부르는데, 이는 암호화의 강도를 나타내는 지표입니다. 쉽게 말하면 키의 길이라고 할 수 있습니다.

당연하게도 비도가 커지면(키의 길이가 길어지면) 이를 해독하는데 더 많은 시간이 걸리고, 공격자가 브루트포스 공격을 하더라도 더 많은 시간이 걸리게 됩니다.
하지만 반대로 그만큼 연산량이 많아지기 때문에, 성능은 떨어지게 됩니다. 그래서 적당한 비도를 선택하는 것이 중요합니다.

PKI(Public Key Infrastructure): 공개키 기반 구조

이제 HTTPS를 사용하기 위한 마지막 단계인 PKI에 대해 알아보겠습니다.

PKI는 위의 소제목에서도 알 수 있듯, 일종의 사회기반시설(Infra)라고 볼 수 있습니다. 전 세계에서 공용으로 사용하는 공개키를 관리하고, 이를 통해 안전한 통신을 할 수 있도록 도와주는 시스템입니다.

그런데 이게 왜 필요할까요..?

사실은, 조금 전에 알아본 공개키 + 대칭키 방식에도 숨겨진 문제가 있습니다.

상대방을 정말로 신뢰할 수 있나?

무슨 뜬구름 잡는 소리냐구요? 좀 더 자세히 살펴봅시다.

위 과정에서 가장 먼저 Alice는 Bob에게 자신의 공개키를 전달합니다.
그런데 만약 이 둘의 사이에 Charlie가 숨어있다면 어떻게 될까요?
Charlie는 둘 사이의 통신을 가로채어, 자신의 공개키를 Bob에게 전달할 수도 있습니다. 그러면 Bob은 이 공개키로 대칭키를 암호화하여 전달하게 됩니다.
그리고 아무렇지 않은척 대칭키를 Alice의 공개키로 암호화하여 전달하면 이후의 모든 통신을 Charlie가 가로챌 수 있게 됩니다. 이것이 바로 중간자 공격입니다.

자, 이제 어느정도 감이 오실겁니다. 이를 해결하기 위해 등장한 것이 바로 인증서입니다.
일반적인 환경에서 Alice와 Bob은 서버와 클라이언트로 볼 수 있습니다. 서버는 클라이언트에게 자신의 공개키를 전달하고, 클라이언트는 이를 통해 데이터를 주고받죠. 이 과정에서 서버는 자신이 누구인지 증명할 수 있는 인증서를 클라이언트에게 전달합니다.

이 인증서는 CA(Certificate Authority)라는 기관이 발급하며, 이를 통해 서버의 신원을 확인할 수 있습니다. 이를 통해 중간자 공격을 방지할 수 있습니다.

위 그림은 네이버의 인증서를 확인하는 화면입니다. 여기서 NAVER Corp. 라는 조직이 DigiCert Inc라는 CA로부터 발급받은 인증서라는 것을 확인할 수 있습니다.

여기서 조금만 더 집요하게 굴어봅시다. 그렇다면 CA는 누구고, 이 CA는 어떻게 신뢰할 수 있는 것일까요? 여기서 등장하는 두 가지 개념이 있습니다. 바로 RCA(Root Certificate Authority)Certificate Chain(Chain of Trust)입니다.

RCA(Root Certificate Authority): 최상위 인증 기관

RCACA의 최상위 인증 기관입니다. 이름 그대로 전세계 모든 인증 기관의 최상위에 위치하며, 그만큼 명망있고 신뢰도 높은 기관입니다. 대표적으로 VeriSign, DigiCert, COMODO등이 있습니다. 이 RCA는 자신의 서명을 통해 CA에게 인증서를 발급하고, 이를 통해 CA는 다시 하위 CA 혹은 서버에게 인증서를 발급합니다.

Certificate Chain(Chain of Trust): 신뢰 체인

눈치 빠른 분들은 아시겠지만, 위에서 언급한 RCACA의 연속된 관계를 Certificate Chain이라고 합니다.
이는 RCACA에게 인증서를 발급하고, CA는 이를 통해 서버에게 인증서를 발급하는 과정을 말합니다. 이를 통해 서버의 신원을 확인할 수 있습니다.

위 그림은 네이버의 인증서를 확인하는 화면입니다. 여기서 DigiCert Global Root CA라는 최상위 인증 기관이 DigiCert TLS Hybrid ECC SHA384 2020 CA1라는 중간 인증 기관에게 인증서를 발급하고, 이를 통해 *.naver.com이라는 서버에게 인증서를 발급했다는 사실을 알수있죠.

이를 좀 더 개념적으로 정리해보면 아래와 같습니다.

위 그림에서 볼 수 있듯 RCA는 '사회적으로 충분히 신뢰할 수 있는 기관'이므로, 스스로 서명을 하고 인증서를 발급 할 수 있습니다. 그리고 이를 통해 다른 신뢰할 수 있는CA에게 인증서를 발급하고 이를 통해 서버에게 인증서를 발급합니다. 이러한 상속적인 구조를 통해 우리가 흔히 사용하는 수많은 웹사이트들이 자신들의 신원을 보증할 수 있게 됩니다.

자, 그러면 서버의 신원을 보장하는 체계는 알았는데, 우리가 평소에 어떻게 이를 확인하고 있던 것일까요? 혹시 매번 사이트의 인증서를 확인하는 분이 계실까요? 당연히 없을것입니다. 우리를 대신이 브라우저가 이를 대신 확인하고 있기 때문입니다.

저는 맥에서 크롬을 주로 사용하고있는데요, 크롬 브라우저의 '인증서 관리'항목에서 위와 같은 인증서를 확인할 수 있습니다.
앞에서 보았던 DigiCertCOMODO등의 루트 인증 기관 이름이 보이네요.
브라우저는 이러한 루트 인증 기관의 인증서를 내장하고 있어, 이를 통해 서버의 신원을 확인할 수 있습니다. 정확히는 해당 서버의 인증서로부터 하나씩 체인을 거슬러 올라가며 상위 인증기관중 하나를 브라우저가 알고있다면 이를 신뢰할 수 있다고 판단합니다.

이밖에도 RA(Registration Authority), VA(Validation Authority), CRL(Certificate Revocation List)등의 개념이 있지만, 이는 이번 글에서는 다루지 않겠습니다.

본격적인 HTTPS: SSL/TLS 핸드셰이크 과정

이제 본격적으로 HTTPS의 동작원리를 알아보겠습니다.
가장 먼저 알아야 할 개념은 SSL/TLS 핸드셰이크입니다. 이는 클라이언트와 서버가 서로 통신을 시작하기 전에 서로의 신원을 확인하고, 데이터를 암호화하기 위한 키를 교환하는 과정입니다. 이는 아래와 같은 과정을 거칩니다.

우선은 TLS 1.2를 기준으로 단계만 간단히 설명하면 아래와 같습니다.

TLS 1.2 핸드셰이크 과정

  1. Client Hello
  2. Server Hello
  3. Certificate
  4. Server Key Exchange
  5. Server Hello Done
  6. Client Key Exchange
  7. Change Cipher Spec
  8. New Session Ticket

이 과정을 한번 패킷단위로 살펴보겠습니다.

1. Client Hello

이 과정에서 클라이언트는 서버에게 다음과 같은 정보를 전달합니다.

  • 클라이언트가 생성한 랜덤 데이터
  • 클라이언트가 지원하는 암호화 방식(Cipher Suite)
  • 클라이언트가 지원하는 TLS 버전
참고 4) Cipher Suite: 암호화 방식

Cipher Suite는 암호화 방식을 나타내는 것으로, 암호화 알고리즘 + 해시 알고리즘 + 키 교환 알고리즘으로 구성되어 있습니다.

  • TLS_AES_128_GCM_SHA256 (0x1301)
    • TLS 1.3 암호화 스위트로, AES 암호화 알고리즘을 GCM 모드와 함께 사용합니다.
    • AES-128을 사용하며, SHA-256 해시 함수를 이용해 메시지 인증을 수행합니다.
  • TLS_CHACHA20_POLY1305_SHA256 (0x1303):
    • ChaCha20 대칭 키 암호화와 Poly1305 메시지 인증을 사용하는 TLS 1.3 스위트입니다.
    • AES와 달리 모바일 장치와 같이 하드웨어 가속이 없는 환경에서도 효율적으로 사용할 수 있어 주로 이동성에 유리합니다.

2. Server Hello

서버는 클라이언트가 전달한 정보를 바탕으로 다음과 같은 정보를 다시 전달합니다.

  • 서버가 생성한 랜덤 데이터
  • 서버가 선택한 암호화 방식(Cipher Suite)
  • 서버가 선택한 TLS 버전

3. Certificate

서버는 클라이언트에게 자신의 인증서를 전달합니다. 이 인증서는 서버의 공개키를 포함하고 있습니다. 클라이언트는 이를 통해 서버의 신원을 확인하고, 이후의 통신을 위한 대칭키(세션키)를 교환하기 위해 사용합니다.

글씨가 다소 작아서 보기 힘드실 수 있지만, 서버가 클라이언트에게 인증 체인을 전달하고있는 것을 보실 수 있습니다.
맨 아래 파란색 박스를 보시면 SubjectIssuerDigiCert Global Root G2로 같은 것을 확인할 수 있습니다.
즉, 이 인증서는 RCA가 스스로 서명하여 발급한 인증서라는 것을 알 수 있습니다. 그리고 이를 통해 하늘색 박스의 Thawte TLS RSA CA G1라는 CA가 서버에게 인증서를 발급하였고, 다시 이를 통해 *.kakaocdn.net이라는 서버에게 인증서를 발급하였다는 것을 알 수 있습니다.

4. Server Key Exchange

이 단계에서 서버는 클라이언트에게 대칭키(세션키)를 교환하기 위한 정보를 전달합니다. 이 정보는 클라이언트가 서버의 공개키를 이용하여 대칭키를 암호화하여 전달하는데 사용됩니다.

TLS 1.2에서는 RSADH(Diffie-Hellman)를 사용하여 대칭키를 교환합니다. 여기서는 DH, 그중에서도 ECDHE(Elliptic Curve Diffie-Hellman Ephemeral)를 사용한 예시입니다.

참고 5) ECDHE(Elliptic Curve Diffie-Hellman Ephemeral): 타원곡선 디피-헬만

ECDHEDH의 확장판으로, 타원곡선을 이용하여 키 교환을 수행하는 방식입니다. 이 방식은 DH에 비해 더 빠르고 안전하며, 더 적은 연산량을 요구합니다. 이 방식은 TLS 1.2에서 널리 사용되고 있습니다.

기본적으로 DH와 동일한 방식으로 작동하여 서버와 클라이언트가 서로의 공개키를 교환하고, 이를 통해 대칭키를 생성합니다.

DH류의 방식은 사실 이전에 알아보았던 대칭키 + 비대칭키 방식과 다소 다릅니다. 이 방식은 실질적인 대칭키를 교환하는 것이 아니라 서버와 클라이언트가 서로의 공개키와 자신의 비밀키를 이용하여 동일한 대칭키를 생성한다는 점에서 기존에 설명한 RSA 방식과는 다릅니다.

5. Server Hello Done

서버는 클라이언트에게 핸드셰이크 과정이 완료되었음을 알리는 메시지를 전달합니다.
별다른 정보는 없습니다.

6. Client Key Exchange

클라이언트는 서버가 전달한 정보를 바탕으로 ECDHE 알고리즘을 사용하여 대칭키를 생성하고, 서버에 자신의 공개키를 전달합니다. 이 과정을 통해 서버도 클라이언트와 동일한 대칭키를 생성할 수 있게 됩니다.

7. Change Cipher Spec

이제 클라이언트와 서버는 대칭키를 생성하였으므로, 이를 통해 암호화된 통신을 시작할 준비가 되었습니다. 이를 알리기 위해 Change Cipher Spec 메시지를 전달합니다.

8. New Session Ticket

이 과정은 명시적인 핸드셰이크 단계는 아닙니다. 다만, 이제 TLS 연결이 수립되었고, 향후 통신시 불필요한 핸드셰이크 과정을 줄이기 위해 서버는 클라이언트에게 New Session Ticket을 전달합니다. 이를 통해 클라이언트는 이후의 통신에서 검증을 생략하고 빠르게 통신을 할 수 있습니다.

TLS 1.3 핸드셰이크 과정

TLS 1.3에서는 핸드셰이크 과정이 단순화되었습니다. 이전과 달리 Client HelloServer Hello만을 통해 대칭키를 교환하고, 이를 통해 통신을 시작합니다. 이를 통해 핸드셰이크 과정이 간소화되었으며, 더 빠르고 안전한 통신을 가능하게 합니다.

  1. Client Hello
  2. Server Hello
  3. Change Cipher Spec

이번에도 한번 패킷단위로 살펴보겠습니다.

1. Client Hello

TLS 1.3에서는 클라이언트가 서버에게 다음과 같은 정보를 전달합니다.
다른 정보는 이전(TLS 1.2)과 동일합니다. 다만 이제는 클라이언트의 공개키가 key_share 익스텐션을 통해 전달됩니다.

  • 클라이언트가 생성한 랜덤 데이터
  • 클라이언트가 지원하는 암호화 방식(Cipher Suite)
  • 클라이언트가 지원하는 TLS 버전
  • 클라이언트의 공개키

2. Server Hello, Change Cipher Spec

서버는 클라이언트가 전달한 정보를 바탕으로 다음과 같은 정보를 다시 전달합니다.
이전 Client Hello와 동일하게 key_share 익스텐션을 통해 서버의 공개키를 전달합니다.

  • 서버가 생성한 랜덤 데이터
  • 서버가 선택한 암호화 방식(Cipher Suite)
  • 서버가 선택한 TLS 버전
  • 서버의 공개키

3. Change Cipher Spec

여기까지 통신을 마치면 클라이언트와 서버 모두 세션키를 생성할 수 있게 되므로 곧장 이어서 Change Cipher Spec을 전달합니다.

이렇게 TLS 1.3에서는 핸드셰이크 과정이 단순화되어 더 빠르고 안전한 통신을 가능하게 합니다.

위와 같은 과정을 거쳐 TLS 연결이 수립되고나면 서버와 클라이언트는 HTTPS로 통신을 할 수 있게됩니다.
이를 통해 이제는 거의아무도 둘 사시의 통신을 훔쳐볼 수 없게 됩니다.

결론

이번 글에서는 SSL/TLS를 이해하기 위한 기본적인 개념부터, HTTPS의 동작원리, PKI의 개념, SSL/TLS 핸드셰이크 과정까지 다루어 보았습니다.
사실 더 넓은 범위를 다루고싶었지만 분량 문제와 정리 역량 부족 이슈로 이번에는 여기까지만 다루어 보아야겠네요.

최대한 간단하고 이해하기 쉽게 설명하려고 노력했지만, 이해하기 어려운 부분이 있었다면 피드백 주시면 감사드리겠습니다.
피드백이 아니더라도 궁금한 점이나 추가적인 내용이 있다면 언제든지 댓글로 남겨주시면 답변드리겠습니다. 긴 글 읽어주셔서 감사합니다!

profile
안녕하세요

2개의 댓글

comment-user-thumbnail
1일 전

학부생 시절 네트워크 보안 수업에서 제일 좋아하는 파트였는데 그때 기억이 새록새록 떠오르기도 하고 이런게 있었구나 싶기도 하네요 ㅎㅎ

보통 이론 정리에서 끝나는 경우가 많은데 실제 패킷을 까서 포스팅 해주시니 더 이해가 잘 되었어요.
혹시 패킷 캡처 툴은 어떤것을 사용하셨나요?

1개의 답글