jongkwan.dev
개발 · Essay №035

TLS와 HTTPS: 핸드셰이크와 인증서

HTTPS가 키 교환·인증서 검증·암호화로 도청과 변조를 막는 원리를 TLS 1.2와 1.3 기준으로 정리합니다.

이종관2026년 1월 29일11 min read
Contents

HTTPS는 HTTP를 TLS로 감싸 키를 안전하게 합의하고, 인증서로 상대 서버가 진짜임을 확인하는 구조입니다.

HTTPS가 막는 위협

평문 HTTP는 중간 경로의 누구나 내용을 읽고 바꿀 수 있습니다. 공용 와이파이나 통신사 장비처럼 패킷이 지나는 길목이 모두 잠재적 도청 지점입니다. HTTPS는 HTTP 메시지를 전송 계층 보안(Transport Layer Security, TLS)으로 감싸 이 문제를 다룹니다. TLS의 전신은 보안 소켓 계층(Secure Sockets Layer, SSL)이며, 지금은 TLS가 표준입니다.

TLS가 보장하려는 속성은 세 가지로 나뉩니다. 기밀성은 도청을 막고, 무결성은 변조를 탐지하며, 인증은 상대가 사칭이 아님을 확인합니다. RFC 8446은 TLS 1.3의 목적을 도청·변조·위조 방지로 규정합니다.

대칭키와 비대칭키의 분업

대칭키 암호는 같은 키로 암호화와 복호화를 합니다. 빠르지만 양쪽이 같은 키를 미리 나눠 가져야 한다는 문제가 있습니다. 비대칭키 암호는 공개키로 잠그고 개인키로만 푸는 방식이라, 키를 안전하게 건넬 수 있습니다. 다만 연산이 무거워 대용량 데이터에는 부적합합니다.

TLS는 두 방식을 한 연결 안에서 나눠 씁니다. 핸드셰이크 단계에서 비대칭 연산으로 세션 키를 합의하고, 이후 실제 데이터는 빠른 대칭키로 암호화합니다.

위 그림처럼 키 교환의 안전성과 통신의 속도를 함께 얻는 하이브리드 방식입니다.

TLS 1.2 핸드셰이크

전체 핸드셰이크는 두 번의 왕복(Round-Trip Time, RTT)으로 이뤄집니다. 메시지가 오가는 순서는 아래와 같습니다.

ClientHello와 ServerHello에서 양쪽은 지원하는 암호군과 난수를 교환합니다. 서버는 자신의 인증서를 함께 보내고, 클라이언트는 그 인증서를 검증합니다. 이어 클라이언트가 사전 마스터 비밀(Pre-master Secret)을 만들어 서버 공개키로 암호화해 전달합니다. 마지막으로 양쪽은 두 난수와 사전 마스터 비밀로 같은 세션 키를 도출합니다.

세션 키가 만들어지면 Finished 메시지로 핸드셰이크가 정상임을 확인합니다. 이후의 모든 HTTP 데이터는 이 대칭 세션 키로 암호화됩니다. 이 절차는 TLS 1.2를 정의한 RFC 5246에 근거합니다.

인증서와 신뢰 체인

서버 인증서는 도메인과 공개키를 묶고, 인증 기관(Certification Authority, CA)이 서명한 문서입니다. 형식은 X.509 표준을 따르며, 인증서와 폐기 목록 프로파일은 RFC 5280이 정의합니다. 클라이언트는 서버 인증서에서 중간 인증서, 루트 인증서로 이어지는 체인을 따라 서명을 검증합니다. 루트 인증서는 운영체제나 브라우저에 미리 내장된 신뢰 목록에 들어 있습니다.

검증은 서명만 보지 않습니다. 도메인 이름이 인증서의 대상과 일치하는지, 유효기간이 지나지 않았는지도 함께 확인합니다.

검증 항목확인 내용실패 시
서명 체인CA 공개키로 상위 서명 검증신뢰할 수 없는 발급자
도메인 일치접속 호스트명과 인증서 대상 비교호스트명 불일치 경고
유효기간현재 시각이 만료 전인지 확인인증서 만료 오류

암호화가 되어 있어도 인증서 검증이 약하면 중간자(Man-in-the-Middle) 공격에 노출됩니다. 그래서 TLS의 안전성은 암호화만큼이나 서버 인증에 달려 있습니다.

암호화와 무결성

기밀성만으로는 변조를 막지 못합니다. 공격자가 내용을 못 읽어도 암호문 자체를 조작할 수 있기 때문입니다. TLS는 이를 막기 위해 메시지 인증 코드(Message Authentication Code, MAC)나 인증 태그로 무결성을 함께 검사합니다.

현대 TLS는 연관 데이터 인증 암호(Authenticated Encryption with Associated Data, AEAD)를 씁니다. AEAD는 암호화와 무결성 검사를 한 연산으로 묶어, 복호화 때 인증 태그가 맞지 않으면 메시지를 버립니다. RFC 8446은 TLS 1.3에서 AEAD만 허용하도록 정했고, AES-GCM이 대표적인 예입니다.

TLS 1.3의 변화

TLS 1.3은 핸드셰이크를 줄이고 취약한 선택지를 걷어냈습니다. 전체 핸드셰이크가 1-RTT로 줄고, 이전 연결 정보를 재사용하는 0-RTT 재개도 가능합니다. 가장 큰 변화는 정적 RSA 키 전송을 없애고 임시 키 기반 (EC)DHE 교환만 남긴 점입니다.

여기서 ECDHE는 타원곡선 디피-헬먼 임시키(Elliptic Curve Diffie-Hellman Ephemeral) 교환을 뜻합니다. 매 세션마다 임시 키를 새로 만들기 때문에 전방향 비밀성(Forward Secrecy)이 보장됩니다. 전방향 비밀성은 서버 개인키가 나중에 유출돼도 과거 세션을 복호화할 수 없는 속성입니다.

항목TLS 1.2TLS 1.3
전체 핸드셰이크2-RTT1-RTT
세션 재개세션 티켓(제한적)PSK 기반 0-RTT
키 교환RSA·DH·ECDHE 등(EC)DHE만
전방향 비밀성선택필수

표의 항목은 RFC 8446(TLS 1.3)과 RFC 5246(TLS 1.2)을 근거로 합니다. TLS 1.3이 정의한 암호군은 다섯 개로, 모두 AEAD 기반입니다.

운영에서 확인하는 것

실무에서 TLS 문제는 대개 인증서 만료, 체인 누락, 이름 불일치, 종료 지점에서 생깁니다. 명령행에서는 openssl로 핸드셰이크와 인증서를 직접 확인할 수 있습니다.

bash
# 인증서 체인과 핸드셰이크를 확인 (SNI 포함)
openssl s_client -connect example.com:443 -servername example.com
 
# TLS 1.3으로만 협상해 호환성 확인
openssl s_client -connect example.com:443 -tls1_3

여기서 -servername은 서버 이름 표시(Server Name Indication, SNI)를 지정합니다. 한 IP가 여러 도메인을 호스팅할 때, 서버는 SNI를 보고 올바른 인증서를 고릅니다.

또 하나 확인할 것은 TLS 종료 지점입니다. 로드 밸런서나 CDN에서 TLS를 끝내면 그 뒤 내부 구간은 평문일 수 있습니다. 필요하면 재암호화나 상호 TLS(mTLS)로 그 구간을 보호합니다.

TLS는 전송 중 기밀성과 무결성을 담당합니다. 여기에 HTTP 엄격 전송 보안(HTTP Strict Transport Security, HSTS)을 더하면 HTTPS 접속을 강제할 수 있습니다. HSTS는 Strict-Transport-Security 응답 헤더로 정책을 전달하며 RFC 6797이 규정합니다. 다만 XSS나 세션 탈취 같은 애플리케이션 보안은 TLS가 아니라 별도 헤더·토큰·쿠키 정책이 맡습니다.

정리

HTTPS는 HTTP를 TLS로 감싸 기밀성·무결성·인증을 함께 제공합니다. 핸드셰이크는 비대칭 연산으로 세션 키를 합의하고, 이후 통신은 빠른 대칭키로 암호화하는 하이브리드 구조입니다. 신뢰의 출발점은 CA 체인·도메인·유효기간을 보는 인증서 검증이며, 이것이 약하면 암호화가 있어도 중간자 공격에 뚫립니다. TLS 1.3은 핸드셰이크를 1-RTT로 줄이고 임시 키 교환만 남겨 전방향 비밀성을 기본으로 만들었습니다. 운영에서는 openssl로 체인과 버전을 확인하고, TLS 종료 지점 뒤 내부 구간 보호까지 함께 챙기는 것이 좋습니다.