TLS 핸드쉐이크가 무거운 건 비대칭 암호 연산과 왕복(RTT)이 둘 다 비싸기 때문이다
·수정 1회
요약
- TLS 핸드쉐이크는 "인증서 확인" 하나가 아니라 인증·키합의·무결성 세 가지를 동시에 푸는 절차다.
- 무거운 이유는 두 축 — 비싼 비대칭 암호 연산(CPU) + 여러 번의 왕복(RTT). 그래서 "한 번만 비싸게 합의하고 이후엔 대칭키로 싸게" 가는 구조다.
본문
핸드쉐이크가 푸는 문제 3개
"인증서 서로 확인"은 흔한 오해다. 일반 웹(HTTPS)은 보통 클라이언트가 서버 인증서만 확인하고 서버는 클라이언트를 확인하지 않는다(양쪽 다 하면 mTLS). 그리고 인증서 확인은 셋 중 하나일 뿐이다.
| 문제 | 질문 | 해결 |
|---|---|---|
| 인증 | 상대가 진짜 그 서버 맞아? | 인증서 + CA 서명 |
| 키 합의 | 도청당하는 회선에서 비밀키를 어떻게 나눠 갖지? | Diffie-Hellman (ECDHE) |
| 무결성 | 중간에 메시지 바꿔치기 안 했어? | 서명/MAC |
(A) 인증서 — 위조를 왜 못 믿게 되나
- 인증서에는 "이 도메인의 공개키는 이거다"가 적혀 있고, 거기에 CA가 자기 개인키로 서명해 둔다.
- CA의 공개키는 브라우저/OS에 미리 박혀 있다(루트 저장소).
- 위조본은 CA 개인키가 없으니 유효한 서명을 못 만든다. 브라우저가 CA 공개키로 검증하면 불일치 → 거부.
- 보통 체인이다: 서버 인증서 ← 중간 CA 서명 ← 루트 CA. 신뢰하는 루트까지 닿으면 통과.
- (비유: 인증서=여권, CA 서명=외교부 도장. 여권은 복사해도 도장은 못 찍는다.)
(B) 키 교환 — 도청당해도 둘만 아는 키가 생기는 이유
Diffie-Hellman(DH/ECDHE). 핵심은 "섞으면 역산이 안 되는" 연산.
- 둘이 공개 공유값에 합의(도청자도 봐도 됨)
- 각자 자기 개인값은 절대 안 보냄. 대신 (공유값 + 내 개인값)을 섞은 결과만 전송
- 받은 값에 다시 자기 개인값을 섞으면 → 양쪽이 같은 비밀키에 도달
- 도청자는 오가는 값을 다 봐도 개인값이 없어서 그 비밀키를 못 만든다 (페인트는 섞으면 못 분리)
(A)+(B) 결합: DH 교환 메시지에 서버가 인증서 개인키로 서명을 붙여 "이 키 교환을 한 게 진짜 그 서버"임을 보장한다. 안 그러면 중간자가 끼어든다.
(C) 그래서 왜 무겁나 — 두 축
- CPU: (A)(B)가 비대칭 암호 = 큰 수 거듭제곱. 대칭키(AES)보다 수십~수백 배 느리다. 특히 서버가 매 접속마다 개인키 연산을 해서 CPU 병목.
- RTT: 인증서 전달·검증·키 교환을 하려면 양쪽이 여러 번 주고받아야 함. TCP 포함 ~3 RTT. 거리가 멀면 그만큼 지연 누적.
왜 이 구조인가 / 최적화 방향
비싼 비대칭 연산으로 세션키 하나를 합의해두면, 이후 실제 데이터는 싼 대칭키(AES) 로 암호화한다. 비싼 건 시작 때 한 번뿐. 그래서 최적화는 전부 "그 세션키를 재활용"하는 방향:
- 연결 재사용(keep-alive): 핸드쉐이크 자체를 안 함
- 세션 재개(session ticket/ID): 비대칭 연산 생략, 이전 세션키 복원
- TLS 1.3: 풀 핸드쉐이크 1-RTT, 재개 0-RTT
- ECDHE가 RSA 키교환보다 빠르고 forward secrecy 제공