TLS 핸드 쉐이크

클라이언트와 서버가 HTTPS 통신을 시작하기 전에 암호화 알고리즘 협상, 서버 인증, 세션 키 교환을 수행하여 안전한 암호화 채널을 수립하는 과정입니다.

핵심 개념

항목내용
정식 명칭Transport Layer Security Handshake
목적암호화 통신을 위한 사전 협상
위치TCP 3-Way Handshake 이후, 데이터 전송 이전
결과양측이 동일한 세션 키(대칭 키)를 공유
현재 표준TLS 1.3 (2018년)

HTTPS 연결 전체 흐름에서의 위치

클라이언트                              서버
    │                                   │
    │◄──── TCP 3-Way Handshake ────►    │  ① TCP 연결 수립
    │      SYN → SYN-ACK → ACK         │
    │                                   │
    │◄──── TLS Handshake ──────────►    │  ② 암호화 채널 수립
    │      (암호화 협상 + 키 교환)         │
    │                                   │
    │◄──── 암호화된 데이터 통신 ────────►  │  ③ 실제 데이터 전송
    │      (HTTP 요청/응답)              │
    │                                   │

TLS 1.2 Handshake (4단계)

클라이언트                                    서버
    │                                         │
    │──── ① Client Hello ─────────────→       │
    │  - 지원하는 TLS 버전                      │
    │  - 지원하는 암호 스위트 목록                │
    │  - Client Random (난수)                  │
    │                                         │
    │←─── ② Server Hello ─────────────        │
    │  - 선택한 TLS 버전                        │
    │  - 선택한 암호 스위트                      │
    │  - Server Random (난수)                  │
    │                                         │
    │←─── ③ Certificate ──────────────        │
    │  - 서버의 SSL/TLS 인증서 (공개 키 포함)     │
    │                                         │
    │←─── ④ Server Hello Done ────────        │
    │                                         │
    │  [클라이언트: 인증서 검증]                   │
    │  - 인증 기관(CA) 서명 확인                  │
    │  - 유효 기간 확인                          │
    │  - 도메인 일치 확인                         │
    │                                         │
    │──── ⑤ Client Key Exchange ──────→       │
    │  - Pre-Master Secret                    │
    │    (서버 공개 키로 암호화하여 전송)           │
    │                                         │
    │  [양쪽: 세션 키 생성]                       │
    │  Client Random + Server Random           │
    │  + Pre-Master Secret → 세션 키 도출        │
    │                                         │
    │──── ⑥ Change Cipher Spec ───────→       │
    │  "이제부터 암호화 통신합니다"                 │
    │                                         │
    │──── ⑦ Finished (암호화) ────────→        │
    │                                         │
    │←─── ⑧ Change Cipher Spec ───────        │
    │←─── ⑨ Finished (암호화) ────────         │
    │                                         │
    │◄════ 암호화된 통신 시작 ════════►          │

TLS 1.3 Handshake (간소화 — 1-RTT)

TLS 1.3은 왕복 횟수를 줄여 1-RTT(1 Round Trip Time)로 핸드셰이크를 완료합니다.

클라이언트                                    서버
    │                                         │
    │──── ① Client Hello ─────────────→       │
    │  - 지원하는 TLS 버전                      │
    │  - 지원하는 암호 스위트 목록                │
    │  - Client Random                        │
    │  - Key Share (DH 공개 값)  ← 미리 전송  │
    │                                         │
    │←─── ② Server Hello ─────────────        │
    │  - 선택한 암호 스위트                      │
    │  - Server Random                        │
    │  - Key Share (DH 공개 값)                 │
    │                                         │
    │←─── ③ Certificate + Verify ─────        │
    │←─── ④ Finished ─────────────────        │
    │                                         │
    │  [양쪽: DH 공개 값으로 세션 키 즉시 도출]    │
    │                                         │
    │──── ⑤ Finished ─────────────────→       │
    │                                         │
    │◄════ 암호화된 통신 시작 ════════►          │

TLS 1.2 vs TLS 1.3

항목TLS 1.2TLS 1.3
왕복 횟수2-RTT1-RTT (재연결 시 0-RTT 가능)
키 교환RSA 또는 DHEDHE/ECDHE만 허용
암호 스위트다양 (일부 취약)안전한 것만 5개로 축소
전방 비밀성선택 사항필수 (Perfect Forward Secrecy)
핸드셰이크 암호화일부만 암호화인증서부터 암호화
성능상대적으로 느림빠름
연결 수립 시간 비교:

TLS 1.2:
  TCP (1 RTT) + TLS (2 RTT) = 3 RTT

TLS 1.3:
  TCP (1 RTT) + TLS (1 RTT) = 2 RTT

TLS 1.3 재연결 (0-RTT):
  TCP (1 RTT) + TLS (0 RTT) = 1 RTT ← 이전 세션 정보 재사용

핸드셰이크에서 사용하는 암호화 방식

단계암호화 방식목적
키 교환비대칭 암호화 (RSA, ECDHE)세션 키를 안전하게 교환
서버 인증디지털 인증서 (CA 서명)서버 신원 확인
데이터 전송대칭 암호화 (AES-GCM 등)실제 데이터 암호화 (빠름)
왜 비대칭 + 대칭을 함께 사용하는가?

비대칭 암호화 (RSA, ECDHE):
  - 장점: 키 교환이 안전
  - 단점: 매우 느림 (데이터 전송에 부적합)

대칭 암호화 (AES):
  - 장점: 매우 빠름 (데이터 전송에 적합)
  - 단점: 키를 어떻게 안전하게 공유할 것인가?

→ 해결: 비대칭으로 대칭 키를 교환 → 이후 대칭 키로 통신

┌──────────────────────────────────────────┐
│  TLS Handshake (비대칭 암호화)              │
│  → 세션 키(대칭 키) 교환                    │
├──────────────────────────────────────────┤
│  데이터 전송 (대칭 암호화)                   │
│  → 세션 키로 빠르게 암호화/복호화             │
└──────────────────────────────────────────┘

인증서 검증 과정

서버 인증서 수신
    │
    ▼
① 인증서 체인 확인
   서버 인증서 → 중간 CA 인증서 → 루트 CA 인증서
                                      ↑
                               브라우저에 내장된
                               신뢰할 수 있는 루트 CA 목록

② CA 서명 검증
   CA의 공개 키로 인증서의 디지털 서명 확인
   → 위조되지 않았는지 확인

③ 유효 기간 확인
   현재 날짜가 인증서의 유효 기간 내인지 확인

④ 도메인 일치 확인
   인증서의 CN/SAN 필드가 접속한 도메인과 일치하는지 확인

⑤ 폐기 여부 확인
   CRL 또는 OCSP로 인증서가 폐기되었는지 확인

  모두 통과 → 핸드셰이크 계속
  하나라도 실패 → 경고 또는 연결 거부

전방 비밀성 (Perfect Forward Secrecy)

항목RSA 키 교환DHE/ECDHE 키 교환
전방 비밀성없음있음
서버 개인 키 유출 시과거 모든 통신 복호화 가능과거 통신 복호화 불가
세션 키 생성서버 개인 키에 의존매 세션마다 임시 키 쌍 생성
TLS 1.3사용 불가 (제거됨)필수
[RSA — 전방 비밀성 없음]
서버 개인 키 유출 → 과거에 캡처해둔 모든 트래픽 복호화 가능

[ECDHE — 전방 비밀성 있음]
세션 1: 임시 키 쌍 A 사용 → 세션 종료 → 키 폐기
세션 2: 임시 키 쌍 B 사용 → 세션 종료 → 키 폐기

서버 개인 키 유출되어도:
  → 임시 키는 이미 폐기됨
  → 과거 트래픽 복호화 불가

Java에서의 TLS 핸드셰이크

// HTTPS 연결 시 내부적으로 TLS 핸드셰이크 수행
HttpsURLConnection conn = (HttpsURLConnection)
    new URL("https://example.com").openConnection();
conn.connect();  // TCP 연결 + TLS 핸드셰이크 수행

// 연결 후 TLS 정보 확인
System.out.println("암호 스위트: " + conn.getCipherSuite());
// ex) TLS_AES_256_GCM_SHA384

Certificate[] certs = conn.getServerCertificates();
X509Certificate cert = (X509Certificate) certs[0];
System.out.println("발급자: " + cert.getIssuerDN());
System.out.println("만료일: " + cert.getNotAfter());

// Spring WebClient에서 TLS 설정
SslContext sslContext = SslContextBuilder.forClient()
    .trustManager(InsecureTrustManagerFactory.INSTANCE) // 개발용 (운영 금지)
    .protocols("TLSv1.3")  // TLS 1.3 강제
    .build();

→ TLS 핸드셰이크 과정에 대해 설명해주세요

CSLOG에서 보기