보안Medium#86
HTTPS와 TLS 핸드셰이크 과정을 설명해주세요.
#보안#HTTPS#TLS#암호화#네트워크
힌트
대칭키와 비대칭키 암호화가 혼합 사용되는 이유를 생각해보세요.
정답 및 해설
HTTPS와 TLS 핸드셰이크 과정을 설명해주세요.
HTTPS(HyperText Transfer Protocol Secure)는 기존 HTTP에 TLS(Transport Layer Security) 암호화 계층을 추가하여 데이터의 기밀성, 무결성, 인증을 보장하는 프로토콜입니다. 오늘날 모든 웹 서비스에서 사용자 데이터를 도청, 변조, 위조로부터 보호하기 위한 필수 요소입니다.
HTTP vs HTTPS
| 항목 | HTTP | HTTPS |
|---|---|---|
| 포트 | 80 | 443 |
| 암호화 | 없음 (평문 전송) | TLS로 암호화 |
| 인증서 | 불필요 | CA 서명 인증서 필요 |
| 속도 | 빠름 | 핸드셰이크 오버헤드 있음 |
| SEO | 불리 | 구글 우대 |
TLS와 SSL의 관계
SSL(Secure Sockets Layer)은 TLS의 전신으로, 현재는 보안 취약점으로 인해 모두 deprecated 되었습니다.
| 버전 | 상태 |
|---|---|
| SSL 2.0 / 3.0 | Deprecated (취약점 다수) |
| TLS 1.0 / 1.1 | Deprecated (2020년 이후) |
| TLS 1.2 | 현재 주로 사용 |
| TLS 1.3 | 최신 버전, 핸드셰이크 간소화 |
TLS 핵심 암호화 개념
TLS는 두 종류의 암호화를 조합하여 사용합니다.
비대칭키 암호화 (공개키 암호화)
공개키로 암호화 → 개인키로만 복호화
개인키로 서명 → 공개키로 검증
- 장점: 키 교환 없이 안전한 통신 가능
- 단점: 연산 비용이 높아 대용량 데이터 암호화에 부적합
- 사용: TLS 핸드셰이크 과정의 키 교환
대칭키 암호화
같은 키로 암호화, 복호화
- 장점: 연산 속도가 빠름
- 단점: 키를 안전하게 교환하는 것이 어려움
- 사용: 실제 HTTP 데이터 암호화
TLS 1.2 핸드셰이크 과정
클라이언트 서버
| |
|------ 1. Client Hello ------------------>|
| - 지원하는 TLS 버전 |
| - 지원하는 암호화 알고리즘 목록 |
| - 랜덤 데이터 (Client Random) |
| |
|<----- 2. Server Hello -------------------|
| - 선택된 TLS 버전 |
| - 선택된 암호화 알고리즘 |
| - 랜덤 데이터 (Server Random) |
| |
|<----- 3. Certificate ---------------------|
| - 서버 인증서 (공개키 포함) |
| |
|<----- 4. Server Hello Done ---------------|
| |
| [인증서 유효성 검증] |
| - CA 서명 확인 |
| - 만료일 확인 |
| - 도메인 일치 확인 |
| |
|------ 5. Client Key Exchange ------------>|
| - Pre-Master Secret을 서버 공개키로 |
| 암호화하여 전송 |
| |
| [양측에서 동일한 Master Secret 생성] |
| Master Secret = PRF(Pre-Master, |
| Client Random, Server Random) |
| |
| [Master Secret에서 세션 키 도출] |
| |
|------ 6. Change Cipher Spec ------------->|
| - 이제부터 암호화 통신 시작 |
| |
|------ 7. Finished (암호화됨) ------------>|
| |
|<----- 8. Change Cipher Spec -------------|
|<----- 9. Finished (암호화됨) ------------|
| |
|====== 암호화된 HTTP 통신 시작 ============|
1단계: Client Hello
클라이언트가 서버에 연결 요청을 보냅니다.
Client Hello:
- Version: TLS 1.2
- Random: 4a3f2b1c... (32바이트 랜덤)
- Session ID: (세션 재사용 시)
- Cipher Suites:
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
...
- Extensions: SNI, ALPN 등
2단계: Server Hello
서버가 지원 가능한 알고리즘을 선택합니다.
Server Hello:
- Version: TLS 1.2
- Random: 7e8d9a2b... (32바이트 랜덤)
- Session ID: ...
- Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (선택)
암호화 스위트 이름 해석:
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
| | | | | | |
| | | | | | +-- 해시 알고리즘 (무결성)
| | | | | +------ 인증 모드
| | | | +---------- 키 길이 (비트)
| | | +--------------- 대칭 암호화 알고리즘
| | +----------------------- 인증서 서명 알고리즘
| +----------------------------- 키 교환 방식
+---------------------------------- 프로토콜
3단계: 인증서 검증
클라이언트가 서버 인증서의 유효성을 CA(Certificate Authority)를 통해 검증합니다.
인증서 검증 체인:
서버 인증서 (leaf)
↑ 서명
중간 CA 인증서
↑ 서명
루트 CA 인증서 (브라우저/OS에 내장)
// 인증서에 포함된 정보 (개념적)
const certificate = {
subject: "CN=example.com, O=Example Inc, C=KR",
issuer: "CN=Let's Encrypt R3, O=Let's Encrypt",
validFrom: "2024-01-01",
validTo: "2024-04-01",
publicKey: "MIIBIjANBgkq...", // 서버 공개키
signature: "ABC123...", // CA의 개인키로 서명
subjectAltNames: ["example.com", "www.example.com"]
};
4~5단계: 키 교환
Pre-Master Secret을 안전하게 교환합니다. 키 교환 방식에 따라 다릅니다.
RSA 키 교환 (구식, Forward Secrecy 없음):
클라이언트: Pre-Master Secret 생성
→ 서버 공개키로 암호화
→ 서버로 전송
서버: 개인키로 복호화 → Pre-Master Secret 획득
ECDHE 키 교환 (현대적, Forward Secrecy 보장):
클라이언트: 임시 키 쌍 생성 (공개키 전송)
서버: 임시 키 쌍 생성 (공개키 전송)
양측: Diffie-Hellman 알고리즘으로 동일한 공유 비밀 생성
(Pre-Master Secret을 네트워크로 전송하지 않음)
6~9단계: 세션 키 생성 및 통신 시작
// 세션 키 도출 과정 (개념적)
const masterSecret = PRF(
preMasterSecret,
"master secret",
clientRandom + serverRandom
);
// 세션 키 = 여러 개의 키 도출
const keys = PRF(masterSecret, "key expansion", serverRandom + clientRandom);
// → clientWriteKey, serverWriteKey, clientWriteIV, serverWriteIV
TLS 1.3 개선사항
TLS 1.3은 핸드셰이크를 대폭 간소화했습니다.
TLS 1.2: 2-RTT (왕복 2회)
TLS 1.3: 1-RTT (왕복 1회), 0-RTT (세션 재개 시)
클라이언트 서버
| |
|------ Client Hello + Key Share ---------->|
| (키 교환 정보를 Hello에 포함) |
| |
|<----- Server Hello + Key Share ----------|
|<----- Certificate (암호화됨) ------------|
|<----- Finished (암호화됨) --------------|
| |
|------ Finished -------------------------->|
| |
|====== 암호화된 통신 시작 ================|
TLS 1.3에서 제거된 취약한 기능들:
| 제거된 항목 | 이유 |
|---|---|
| RSA 키 교환 | Forward Secrecy 없음 |
| SHA-1, MD5 | 취약한 해시 |
| RC4, DES, 3DES | 취약한 암호화 |
| Renegotiation | 공격 벡터 |
HTTPS 관련 보안 설정
# Nginx HTTPS 설정 예시
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# TLS 버전 제한
ssl_protocols TLSv1.2 TLSv1.3;
# 강력한 암호화 알고리즘만 허용
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
# HSTS (HTTP로 접근 차단)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# OCSP Stapling (인증서 유효성 캐싱)
ssl_stapling on;
ssl_stapling_verify on;
}
정리
| 단계 | 방향 | 내용 |
|---|---|---|
| Client Hello | 클→서 | 지원 알고리즘 목록, 클라이언트 랜덤 |
| Server Hello | 서→클 | 알고리즘 선택, 서버 랜덤 |
| Certificate | 서→클 | 서버 인증서 (공개키 포함) |
| Key Exchange | 클→서 | Pre-Master Secret 전달 |
| 세션 키 생성 | 양측 | Master Secret → 세션 키 도출 |
| Finished | 양방향 | 핸드셰이크 완료, 대칭키 암호화 시작 |
핵심 원리: 비대칭키(공개키)는 초기 키 교환에만 사용하고, 실제 데이터 전송에는 속도가 빠른 대칭키(세션 키)를 사용합니다.