일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- DevOps
- docker
- IAC
- K8S
- kernel
- AWS
- POD
- FastAPI
- EC2
- Deployment
- Network
- cpu
- AZ-900
- elasticsearch
- AZ-104
- AZURE
- asyncio
- Python
- ebs
- asgi
- ansible
- RBAC
- Django
- IAM
- Kubernetes
- Service
- Role
- leetcode
- terraform
- 자바스크립트
- Today
- Total
궁금한게 많은 개발자 노트
[ HTTPS ] TLS HandShake 과정 본문
TLS(Transport Layer Security)란 넷스케이프가 개발한 SSL(Secure Socket Layer)이라는 암호화 프로토콜에서 발전한 것으로, 인터넷에서 데이트를 암호화하여 안전하게 전송하기 위한 프로토콜입니다. HTTP, SMTP, FTP등 다양한 프로토콜 위에서 보안 계층으로 작동합니다. TLS의 주요 목적은 암호화를 통해 탈취 및 변조 방지, 데이터의 무결성 검증, 서버 또는 클라이언트의 신원 확인입니다.
주로 사용되는 예로는 HTTP + TLS를 통한 HTTPS통신입니다.
TLS를 구성하는 핵심 요소로는 암호화 알고리즘, 키 교환 알고리즘, 해시 알고리즘, 디지털 인증서 4가지로 구성됩니다.
- 암호화 알고리즘 : 실제 데이터를 암호화하는데 사용되며, TLS핸드쉐이킹에서는 비대칭키, 전송 시에는 대칭키 알고리즘을 사용
- 대칭키와 비대칭키
대칭키 암호화: 대칭키는 하나의 키를 사용해 데이터를 암호화하고 복호화하는 방식입니다. 이 방식은 계산량이 적어 빠르고 효율적이지만, 사전에 송신자와 수신자가 안전하게 공유할 수 있는 방법이 필요합니다.
비대칭키 암호화: 비대칭키는 공개키와 개인키로 이루어진 두 개의 키를 사용합니다. 공개키는 모두에게 알려져 있고, 개인키는 소유자만이 알고 있어야 합니다. 데이터는 공개키를 이용해 암호화되고, 개인키를 이용해 복호화할 수 있습니다. 이 방식은 보안성이 높지만 계산량이 많아 상대적으로 느립니다. - 사용 시점 : 핸드쉐이크 이후에 클라이언트와 서버 둘 다 세션 키로 데이터를 암호화하여 통신 시 사용
- 대칭키와 비대칭키
- 키 교환 알고리즘 : 클라이언트와 서버가 서로 안전하게 세션 키를 교환/생성할 수 있도록 함
- 사용 시점 : 핸드쉐이크 중 세션 키를 만들기 전에 사용 (TLS 1.3에서는 ECDHE만 사용)
- 실제 사용 위치 : 클라이언트 > 서버 ClientKeyExchange 메시지에서 사용
- 디지털 인증서 및 서명 (Authentication / Digital Certificate) : 서버 또는 클라이언트의 신원을 증명
- 사용 시점 : 핸드쉐이크 중 서버가 Certificate메시지에서 클라이언트에 전달 (X.509인증서 PEM형식 또는 RSA 서명)
- 클라이언트가 ServerHello에서 받은 인증서를 검증, 공개키는 KeyExchage에서 사용되고, 인증서는 CA체인을 통해 신뢰 확인
- 해시 함수 / MAC (Hash / MAC Algorithm) : 메세지 무결성 검증 (변조 여부 확인)
- HMAC 또는 AEAD (Authenticated Encryption with Associated Data)구조로 사용됨
- 핸드쉐이크 메시지 검증 시 사용 (Finished 메시지 포함)
- 실제 데이터 통신 시에도 암호화 + MAC 방식 적용 (SHA-256, SHA-384)
- 실제 사용 위치 : FInished 메시지를 암호화하고 MAC 포함, Application Data에 대해 HMAC이 붙거나 AEAD 방식 사용
구성 요소 | 사용 시점 |
목적 | 대표 알고리즘 |
암호화 알고리즘 | 핸드쉐이크 이후 | 실제 데이터 암호화 (기밀성) | AES-128-GCM, ChaCha20 |
키 교환 알고리즘 | 핸드쉐이크 중 | 세션 키 생성 (비밀 공유) | RSA, ECDHE, DHE |
디지털 인증서 | 핸드쉐이크 중 | 서버(또는 클라이언트) 인증 (신뢰성) | X.509 인증서, RSA 서명 |
해시 / MAC 알고리즘 | 핸드쉐이크 + 데이터 전송 | 무결성 보장 | SHA-256, HMAC, AES-GCM (AEAD) |
Diffie-Hellman 핸드셰이크는 TLS에서 세션 키를 안전하게 공유하기 위해 사용되는 키 교환 알고리즘 기반의 핸드셰이크 방식입니다.
공개키 암호화 없이, 중간자가 감청하더라도 공유 비밀 키(세션 키)를 도출할 수 없게 만드는 프로토콜입니다.
Diffie-Hellman (DH) 기본 개념
**Diffie-Hellman 키 교환(DH)**은 다음 특징을 갖습니다:
- 클라이언트와 서버가 비밀을 공유하지 않고도 서로 동일한 비밀 키를 계산함
- 중간자가 통신 내용을 모두 본다고 해도, 비밀 키를 계산할 수 없음
- 수학적으로 **이산 로그 문제 (Discrete Log Problem)**에 기반한 보안성 제공
기본 DH 키 교환 절차
(단순한 DH 알고리즘 설명)
- 클라이언트와 서버는 공개 파라미터 p(소수), g(원시근)를 공유
- 클라이언트: 비밀 키 a 선택 → A = g^a mod p 계산 → 서버에 전송
- 서버: 비밀 키 b 선택 → B = g^b mod p 계산 → 클라이언트에 전송
- 각자 세션 키 계산:
- 클라이언트: K = B^a mod p
- 서버: K = A^b mod p
TLS에서의 DH 핸드셰이크 방식
TLS에서는 아래의 DH 기반 변형들이 쓰입니다:
DHE (Ephemeral Diffie-Hellman)
– 임시 키 기반
- TLS 1.2에서 사용
- 각 세션마다 임시 DH 키 생성 → Perfect Forward Secrecy 제공
- Cipher Suite 예: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
ECDHE (Elliptic Curve DHE)
– 더 빠르고 안전한 곡선 기반
- Elliptic Curve 수학 기반의 DH
- 성능과 보안 모두 우수
- TLS 1.3에서 기본 키 교환 방식
- Cipher Suite 예: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
[ TLS 핸드쉐이크에서 ECDHE 사용 흐름 ]
ClientHello (ECDHE 지원 명시)
↓
ServerHello (ECDHE 선택)
↓
ServerKeyExchange (서버 ECDHE 공개키 포함)
↓
ClientKeyExchange (클라이언트 ECDHE 공개키 전송)
↓
서버/클라이언트 각각 동일한 세션 키 계산
↓
암호화된 Finished 메시지 → 통신 시작
- Diffie-Hellman 핸드셰이크는 세션 키를 안전하게 공유하는 TLS 키 교환 방식입니다.
- DHE/ECDHE는 매 세션마다 새 키를 생성하여 Perfect Forward Secrecy를 제공합니다.
- TLS 1.3에서는 ECDHE가 기본으로 사용되며, 키 교환 보안성을 크게 강화했습니다.
TLS가 이루어지기 위해서는 TLS 핸드쉐이크 과정이 진행되어야 합니다. TLS 핸드쉐이크는 클라이언트와 서버가 서로를 확인하고 암호화 키를 교환하는 과정으로 이 후 실제 데이터도 해당 키를 기반으로 암호화되어 전송됩니다. TLS핸드쉐이크는 사용자가 HTTPS를 통해 사이트를 탐색하고 브라우저가 처음으로 해당 웹 사이트의 원본 서버를 쿼리하기 시작할 때마다 발생합니다.
TLS 핸드쉐이크 시에는 사용할 TLS버전 지정, 암호화 방법 결정, 서버의 공개 키와 SSL인증서 기관의 디지털 서명을 통해 서버 ID를 인증하고 핸드쉐이크가 완료된 후에 대칭 암호화를 통해 데이터 전송을 하기 위한 세션 키를 생성합니다.
TLS핸드쉐이크가 이루어지는 단계에 대해 상세히 알아보겠습니다. (TCP통신을 먼저 진행해서 통로를 생성한 다음 TLS를 진행)
ClientHello : 클라이언트가 서버로 헬로 메시지를 전송하면서 핸드쉐이크를 시작합니다. 이 메시지에는 클라이언트가 지원하는 TLS버전, 지원되는 암호화 제품군, 그리고 클라이언트 무작위라고하는 무작위 바이트 문자열이 포함됩니다. (이전에 SSL핸드 쉐이크 완료되었다면 그때 생성했던 Session ID를 함께 전달) (SNI포함 SNI란 접속하고자하는 서버 도메인 이름을 ClientHello메시지에 넣기 위한 TSL확장기능으로 서버는 이 정보를 보고 적절한 인증서를 선택)
SeverHello : 클라이언트가 보낸 ClientHello에 대한 서버의 응답으로 TLS인증서(공개키 포함, 일반적으로 X.509형식), TLS Version, 클라이언트가 보낸 암호화 방식 중 서버가 가능한 암호화 방식을 선택하고 마찬가지로 서버 랜덤 바이트 문자열, Session ID를 전달합니다.
ServerHelloDone: 서버가 클라이언트에게 보낼 메시지를 모두 보냈다는 의미
Client가 Server 인증서 검증 : 브라우저는 서버의 TLS인증서가 믿을 만한지 확인하는 단계를 거치며, 대부분의 브라우저에는 공신력 있는 CA가 만든 공개키가 이미 설치되어 있습니다. 서버가 보낸 TSL인증서가 정말 CA가 만든 것인지 확인하기 위해 내장된 CA공개키로 암호화된 인증서를 복화화해봅니다. 정상적인 복호화가 이루어졌다면 CA가 발급한 것이 증명되고 사이트 공개키 및 정보를 획득하게 됩니다. 이 과정에서 서버가 실제 인증서에 명시된 서버인지, 해당 도메인의 소유자인지, 인증서 유효 기간이 지나지 않았는지를 확인할 수 있습니다.
(제 3자 인증기관 CA(Certificate Authority)를 통해 사용자가 접속한 서버의 인증서를 신뢰할 수 있는지 검증합니다. 인증서 체인을 통해 서버 인증서를 검증하며, 미리 저장된 CA공개키로 CA서명을 검증한다면 인증서에 포함된 서버의 공개키가 서버의 것이 맞으며, 서버는 믿을만하다고 판단됩니다.)
Client PreMaster Secret생성 : 클라이언트가 premaster secret이라고 하는 무작위 48바이트 문자열을 하나 더 전송합니다. 예비 마스터 암호는 인증서로부터 전달받은 서버의 공개키로 암호화되어 있으며, 서버가 개인 키로만 해독할 수 있습니다.
Server PreMaster Secret 복호화 : 서버는 개인키를 통해 premaster secret을 복호화 한 값을 master secret값으로 저장합니다. 이것을 사용하여 방금 브라우저와 암호화된 통신을 위해 만들어진 session에 고유한 값을 부여하기 위한 session key를 생성합니다. 세션 키는 대칭키 암호화에 사용할 키이며, 이것으로 브라우저와 서버 사이에 주고받는 데이터를 암호화하고 복호화합니다. (생성 완료 응답)
(클라이언트와 서버 모두 클라이언트 무작위 바이트, 서버 무작위 바이트, premaster key를 조합하여 세션 키 생성)
Client Ready & Server Ready : 클라이언트가 세션 키로 암호화된 완료 메시지를 전송하면 서버도 복호화 후 세션키로 암호화된 완료 메시지를 전송합니다. 이로써 핸드 쉐이킹이 완료되고 세션 키를 통해 통신이 계속 진행됩니다. 만약 HTTPS통신이 완료된다면 서로에게 공유된 세션 키를 폐기하고, 여전히 유지되고 있다면 다음 통신에 브라우저는 TLS 핸드쉐이킹 요청이 아닌 세션 ID만 서버에게 전달합니다.
전체 동작방식은 아래 이미지를 참고해도 이해하기가 쉬울 것 같습니다.
TLS 핸드쉐이킹 과정에서는 대칭키 방식과 비대칭키 방식 모두 사용되었습니다. 모든 웹 콘텐츠 전달을 공개키 방식으로 한다면 웹 서버와 브라우저에 많은 부담이 되기에 핸드 쉐이킹 단계까지는 공개키방식, 그 이후의 HTTPS 통신은 대칭키 방식을 사용하는 것입니다.
만약 세션 키가 탈취된다면 세션의 통신 내용은 모두 복호화될 수 있습니다. 하지만 TLSㅇ는 이런 공격에도 대비한 방어책도 갖추고 있습니다. ECDHE, DHE 같은 키 교환 알고리즘은 세션마다 독립적인 키를 생성하여 한 세션의 키가 탈취되어도 다른 세션에는 영향이 없습니다.
또한, TLS 세션 키는 보통 몇 분 몇 시간만 유지되기에 짧은 세션 수명으로 공격에 사용되기 쉽지 않습니다.
추가로 AEAD를 통해 암호화 + 무결성 검사를 한 번에 처리하여 세션 키가 노출되어도 조작된 데이터는 감지가 가능하며, TLS 1.3은 Perfect Forward Secrecy (PFS)를 강제하므로 훨씬 안전합니다.
'Back End' 카테고리의 다른 글
API 디자인 (REST, GraphQL, gRPC, WebSocket) (4) | 2024.09.17 |
---|---|
[ Fluent Bit ] Backpressure 해결책 Buffering (0) | 2024.05.28 |
[ FastAPI ] Streaming large size file using StreamingResponse (0) | 2024.04.22 |
[ Python] aiobotocore를 사용한 AWS S3와 연동 (0) | 2024.02.08 |
[ FastAPI ] 비동기 메커니즘 (0) | 2023.12.11 |