[Daily morning study] HTTPS와 TLS 핸드셰이크 과정
#daily morning study
HTTPS란
HTTP에 TLS(Transport Layer Security) 암호화를 씌운 프로토콜이다. 데이터를 평문으로 주고받는 HTTP와 달리, HTTPS는 전송 구간 전체를 암호화해서 도청·변조·위장을 막는다.
- 기밀성(Confidentiality): 제3자가 패킷을 캡처해도 내용을 읽을 수 없음
- 무결성(Integrity): 중간에서 데이터가 변조되면 탐지됨
- 인증(Authentication): 서버가 신뢰할 수 있는 주체임을 인증서로 증명
TLS는 SSL의 후속 표준으로, 현재 실무에서 쓰이는 버전은 TLS 1.2와 TLS 1.3이다.
TLS 핸드셰이크 — TLS 1.2
TLS 1.2는 클라이언트와 서버가 여러 번 메시지를 주고받으며 세션 키를 협상한다. 연결에 2 RTT(Round Trip Time) 가 필요하다.
Client Server
│ │
│──── ClientHello ──────────────────────► │
│ (지원 TLS 버전, Cipher Suites, │
│ 클라이언트 랜덤값) │
│ │
│ ◄── ServerHello ───────────────────────│
│ (선택된 Cipher Suite, │
│ 서버 랜덤값) │
│ ◄── Certificate ────────────────────── │
│ (서버 인증서) │
│ ◄── ServerHelloDone ─────────────────── │
│ │
│──── ClientKeyExchange ────────────────► │
│ (Pre-Master Secret, 공개키로 암호화) │
│──── ChangeCipherSpec ─────────────────► │
│──── Finished ─────────────────────────► │
│ │
│ ◄── ChangeCipherSpec ──────────────────│
│ ◄── Finished ──────────────────────────│
│ │
│◄══════ 암호화된 애플리케이션 데이터 ══════│
단계별 설명
1. ClientHello
클라이언트가 먼저 말을 건다.
- 지원 가능한 TLS 버전 목록
- 지원 Cipher Suite 목록 (예:
TLS_RSA_WITH_AES_128_GCM_SHA256) - 클라이언트 랜덤값 (28바이트 난수)
- 세션 ID, SNI(Server Name Indication) 등
2. ServerHello + Certificate + ServerHelloDone
서버가 협상 결과와 인증서를 전달한다.
- ServerHello: 선택된 TLS 버전·Cipher Suite, 서버 랜덤값
- Certificate: 서버의 X.509 인증서 (공개키 포함)
- ServerHelloDone: 협상 메시지 종료 신호
클라이언트는 인증서를 검증한다.
- 인증서의 디지털 서명을 CA의 공개키로 검증
- 인증서 유효기간 확인
- 도메인 이름 일치 여부 확인
- 인증서 폐기 여부 확인 (CRL 또는 OCSP)
3. ClientKeyExchange + Pre-Master Secret
클라이언트가 Pre-Master Secret을 생성하고, 서버 공개키로 암호화해서 전송한다. 이 값은 서버의 개인키가 있어야만 복호화할 수 있다.
4. 세션 키 생성
양쪽 모두 아래 3가지를 갖게 된다.
- 클라이언트 랜덤값
- 서버 랜덤값
- Pre-Master Secret
이 세 값으로 Master Secret을 계산하고, 여기서 실제 암호화에 쓸 세션 키(대칭키)를 파생한다.
5. ChangeCipherSpec + Finished
이제부터 협상한 세션 키로 암호화하겠다고 알리고, 핸드셰이크 메시지 전체의 해시를 교환해서 서로 동일하게 협상했음을 검증한다.
TLS 1.3 — 더 빠르고 더 안전하게
TLS 1.3은 2018년 RFC 8446으로 표준화됐다. 핸드셰이크를 1 RTT로 줄이고, 취약한 암호 알고리즘을 제거했다.
Client Server
│ │
│──── ClientHello ──────────────────────► │
│ (Key Share 포함) │
│ │
│ ◄── ServerHello ───────────────────────│
│ ◄── {Certificate} ─────────────────────│ ← 이미 암호화
│ ◄── {CertificateVerify} ───────────────│
│ ◄── {Finished} ────────────────────────│
│ │
│──── {Finished} ───────────────────────► │
│ │
│◄══════ 암호화된 애플리케이션 데이터 ══════│
TLS 1.3의 주요 변경점
| 항목 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 핸드셰이크 RTT | 2 RTT | 1 RTT |
| 0-RTT 재연결 | 불가 | 가능 (Early Data) |
| 키 교환 방식 | RSA, DHE, ECDHE 등 | ECDHE, DHE만 허용 |
| 폐기된 알고리즘 | RC4, MD5, SHA-1 등 포함 | 완전 제거 |
| 인증서 이후 암호화 | 아니오 | 예 (Certificate도 암호화) |
Forward Secrecy(전방 비밀성)
TLS 1.3은 RSA 키 교환을 제거하고 ECDHE(Diffie-Hellman)만 허용한다. 세션 키가 서버 개인키와 독립적으로 생성되므로, 나중에 개인키가 유출되더라도 과거 세션을 복호화할 수 없다.
0-RTT 재연결
이전에 연결한 서버와 다시 접속할 때, 클라이언트는 저장해둔 PSK(Pre-Shared Key)로 첫 번째 요청부터 데이터를 보낼 수 있다. 다만 재전송 공격(Replay Attack)에 취약할 수 있어서 사용 시 주의가 필요하다.
인증서와 CA 체계
서버 인증서는 인증기관(CA, Certificate Authority) 이 서명해서 신뢰를 보증한다.
Root CA (자체 서명, OS/브라우저에 사전 탑재)
└── Intermediate CA (Root CA가 서명)
└── 서버 인증서 (Intermediate CA가 서명)
브라우저는 인증서 체인을 따라 올라가다가 신뢰할 수 있는 Root CA가 나오면 검증을 통과시킨다. 이걸 Chain of Trust라고 한다.
인증서 유형
| 유형 | 검증 수준 | 주요 특징 |
|---|---|---|
| DV (Domain Validation) | 도메인 소유 확인만 | 발급 빠름, Let’s Encrypt |
| OV (Organization Validation) | 조직 실체 확인 | 회사 정보가 인증서에 표시 |
| EV (Extended Validation) | 강화된 조직 검증 | 브라우저 주소창에 회사명 표시 |
대칭키 vs 비대칭키
TLS는 두 가지 암호화 방식을 조합해서 쓴다.
비대칭키 암호화 (핸드셰이크 단계)
- 공개키로 암호화, 개인키로 복호화
- RSA, ECDH 등
- 연산이 느려서 세션 전체 데이터 암호화에는 부적합
- 세션 키를 안전하게 교환하는 용도로만 사용
대칭키 암호화 (데이터 전송 단계)
- 동일한 키로 암호화·복호화
- AES-GCM, ChaCha20-Poly1305 등
- 연산이 빠름
- 핸드셰이크로 합의한 세션 키를 사용
실제 연결 확인
# 서버의 TLS 인증서와 핸드셰이크 정보 확인
openssl s_client -connect example.com:443 -tls1_3
# 인증서 체인 보기
openssl s_client -connect example.com:443 -showcerts
# curl로 TLS 버전 확인
curl -vI https://example.com 2>&1 | grep -E "SSL|TLS|cipher"
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=example.com
* issuer: C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1
* SSL certificate verify ok.
핵심 정리
- HTTPS = HTTP + TLS. 암호화·무결성·인증을 모두 제공한다.
- TLS 1.2는 2 RTT, TLS 1.3은 1 RTT로 핸드셰이크를 마친다.
- 핸드셰이크에서 비대칭키로 세션 키를 교환하고, 이후 데이터 전송은 빠른 대칭키로 암호화한다.
- TLS 1.3은 Forward Secrecy를 기본 보장하고, 취약한 알고리즘을 모두 제거했다.
- 인증서 체인(Chain of Trust)으로 서버 신원을 검증한다.