안녕하세요 :)
웹사이트에 접속할 때 우리가 흔히 보는 주소는 http:// 또는 https://로 시작합니다. 겉으로 보기엔 단지 s 하나의 차이지만, 실제로는 보안, 암호화, 신뢰라는 관점에서 완전히 다른 세계가 펼쳐집니다.
하지만 대부분의 사람들은 HTTPS가 무엇인지 정확히 알지 못한 채 "그냥 더 안전한 버전이겠지", "보안 강화..된 거 아니야..?" 정도로만 하고 넘깁니다. 심지어 개발자들 사이에서도 "왜 HTTPS가 안전한가?", "어떻게 암호화가 동작하냐?" 이런 질문에 자신 있게 대답하기란 쉽지 않습니다.
그래서 이번 글에서는 HTTP에서 HTTPS로 넘어가는 과정에서 실제로 무슨 일이 벌어지는가에 대해 실제 통신 흐름, 인증서의 역할, TLS의 구조, 대칭키 생성 방식 등 아주 디테일하게 다뤄볼 예정입니다.
함께 다음 질문들에 답해볼 생각입니다.
- HTTPS란 무엇인가
- 인증서는 어떻게 생기고 왜 필요한가?
- TLS는 실제로 어떻게 암호화 통신을 시작하는가?
- Pre-Master Key와 세션 키는 어떤 관계일까?
- HTTPS는 어떻게 데이터를 안전하게 주고받을까?
HTTPS는 왜 HTTP보다 안전한가
HTTP는 무엇일까요?
HyperText Transfer Protocol은 웹에서 정보를 주고받을 수 있도록 만들어진 텍스트 기반 프로토콜입니다. HTTP의 단점은 '전송되는 모든 데이터가 암호화되지 않고 Plain Text(평문)'이라는 점에 있습니다.
만약, 로그인 정보를 전송하려고 할 때, ID나 비밀번호 같은 민감한 데이터가 중간자에게 감청당하면 정보가 그대로 노출이 될 수 있습니다. 실제로 Wi-Fi 스니핑, 패킷 캡처 같은 기법으로 이런 평문 데이터를 엿볼 수 있죠.
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
username=내이름&password=1234 ← 이게 그대로 날아감!
즉, HTTP로 통신하게 된다면, 이런 민감 정보가 노출이 될 수 있다는 뜻입니다.
HTTP는 암호화가 없기 때문에 누구든 트래픽 중간에 끼어들어 데이터를 가로챌 수 있습니다. 이를 MITM(Man-in-the-Middle), 중간자 공격이라고 합니다.
- 네트워크 라우터, 공공 Wi-Fi, 악성 앱 등이 중간에 끼어들 수 있고,
- 사용자가 모르는 사이에 요청을 가로채거나 변조할 수도 있습니다.
HTTPS는 HyperText Transfer Protocol Secure의 약자입니다. HTTP위에 TLS(Transport Layer Security)라는 보안 계층을 추가한 프로토콜이죠. 즉, HTTP의 전송 내용을 암호화해서 보호해줍니다.
Content Type: Application Data
TLSv1.3 Record Layer: Application Data Protocol
Content Type: Application Data (23)
Version: TLS 1.3
Length: 512
Encrypted Application Data: [Encrypted payload]
이런 식으로 보호를 해주게 됩니다.
이 덕분에
- 누군가 네트워크를 감청하더라도 내용을 볼 수 없습니다. → 왜? 암호화되어 있으니까
- 도중에 누가 데이터를 바꾸더라도 브라우저가 감지합니다. → 어떻게? HTTPS는 무결성 검증을 하니까
- 서버가 진짜인지도 확인할 수 있습니다 → 어떻게? TLS 인증서 기반 신원 검증을 하기 때문에
대충 표로 요약을 해보면 다음과 같습니다.
항목 | HTTP | HTTPS |
전송 데이터 | 평문 (Plain Text) | 암호화됨 |
감청 가능성 | 매우 높음 | 거의 불가능 |
서버 인증 | 없음 | 인증서로 신원 보장 |
브라우저 보안 표시 | 자물쇠 없음 | 🔒자물쇠 아이콘 표시 |
자, 그럼 여기서 의문이 생기죠?
TLS 인증서라는 놈은 뭔데 HTTP에 이런 강력한 보안 효과를 제공하는 걸까?
인증서는 어떻게 생기고 왜 필요한가?
HTTPS 보안의 출발점은 인증서입니다. HTTPS의 중요한 특징 중 하나는 "내가 연결하려는 서버가 진짜 맞는가?"를 확인할 수 있다는 점입니다. 이걸 가능하게 해주는 게 바로 TLS 인증서에요.
브라우저가 https://www.example.com에 접속하면, 서버는 "나 진짜 example.com이야! 나 맞아!!!"라는 것을 증명하기 위해 인증서를 브라우저에게 먼저 보냅니다.
인증서 안에는 뭐가 있을까요?
인증서는 단순한 텍스트 파일이 아닙니다. 이런 정보들이 포함되어 있어요.
항목 | 설명 |
발급 대상 (subject) | 이 인증서가 인증하는 도메인 주소 (example.com) |
공개키 (public key) | 클라이언트가 암호화할 때 사용하는 열쇠 |
발급자 (lssuer) | 이 인증서를 발급한 인증기관(CA)의 정보 |
유효 기간 | 언제부터 언제까지 유효한 인증서인지 |
전자서명 | 발급자의 비공개키로 서명한 값 - 위조 방지의 핵심 |
- 이 모든 정보를 담은 인증서는 X.509포맷으로 정의되고, 보통 -----BEGIN CERTIFICATE----- 이런 식으로 생겼습니다.
그런데 왜 "인증서"를 믿을 수 있는 걸까요?
서버가 자신의 공개키를 그냥 보내는 건 아무런 의미가 없습니다. 클라이언트는 이렇게 생각할 수 있죠.
"그 공개키가 진짜 서버에서 온거라면, example.com의 서버라는 증거는 대체 뭐야? 증거가 없잖아!! 증거가!!!"
이럴까봐 나온 개념이 바로 신뢰체계: PKI 입니다.
PKI: Public Key Infrastructure (공개키 기반 구조)
이 구조에는 다음 3가지 역할이 있습니다.
- 서버: 자기 공개키와 정보를 담은 인증서 발급을 요청함 (CSR)
- CA(인증 기관): 해당 서버가 진짜 도메인 주인인지 확인한 뒤 전자서명
- 브라우저/OS: 미리 신뢰할 수 있는 루트 인증기관(CA) 목록을 내장하고 있음.
클라이언트는 이러한 흐름을 통해 서버를 검증하게 됩니다.
[Root CA] → [Intermediate CA] → [서버 인증서]
↑ ↑ ↑
브라우저에 내장됨 서명으로 검증 인증서 안에 공개키
- 브라우저는 루트 CA를 신뢰하고,
- 루트 CA가 서명한 중간 CA를 믿고,
- 중간 CA가 서명한 서버 인증서를 믿게 되는 것이죠.
이런 걸 인증서 체인(chain of trust)이라고 부릅니다.
만약, 인증서가 없다면?
- 브라우저는 연결을 거부하거나,
- "주의 요함" 또는 "이 사이트는 안전하지 않음"같은 경고를 띄우게 됩니다.
- 즉, 인증서가 없거나 위조되면 HTTPS 통신 자체가 불가능해지는 것이죠.
한 줄로 요약하면 "인증서는 신뢰할 수 있는 기관이 서버의 신원을 보증하고, 안전한 암호화 통신을 시작할 수 있게 해주는 디지털 신분증"이라고 할 수 있습니다. 어디서 많이 들어본 소리죠?
자, 그럼 CA로부터 받은 인증서를 사용해서 암호화 통신을 해야 하는데, 이를 실행하는 TLS에 대해서도 봐보도록 합시다.
TLS는 실제로 어떻게 암호화 통신을 시작하는가?
HTTPS의 핵심은 결국 TLS (Transport Layer Security) 프로토콜입니다.
그런데 여기서 많이 헷갈리는 부분이 있죠.
"서버의 인증서를 받는 건 알겠는데, 그걸 가지고 암호화를 어떻게 시작하는 걸까?"
자, 그러면 TLS Handshake가 실제로 어떻게 이루어지는지, 공개키와 비공개키는 어떤 역할을 하고, 어떻게 둘이 같은 대칭키를 만들 수 있는지 등 낱낱이 뜯어보겠습니다.
어라? 대칭키? 공개키? 비공개키? 이게 뭘까요?
TLS를 이해하려면 이 세 가지 개념을 정확하게 구분할 수 있어야 합니다.
- 대칭키: 하나의 키로 암호화도 하고, 복호화도 하는 방식입니다.
- 아~주 빠릅니다.
- 하지만 키가 유출되면 끝장입니다. ㅎㅎ
- 서버-클라이언트 양쪽이 같은 키를 어떻게 안전하게 공유하느냐가 최대 난관이죠.
- 그래서 실제 데이터 송수신은 모두 대칭키로 진행돼요.
- 비대칭키(공개키/비공개키): 두 개의 서로 다른 키 쌍을 사용하는 방식입니다.
- 공개키: 누구나 볼 수 있고, 암호화할 때 사용됩니다.
- 비공개키: 서버만 가지고 있고, 복호화할 때 사용됩니다.
- 클라이언트는 서버의 공개키로 데이터를 암호화하고,
- 서버만 비공개키로 그 데이터를 복호화할 수 있습니다.
TLS에서 이런 키들이 어떻게 사용될까요?
"공개키/비공개키"는 실제 데이터를 주고받는 데는 쓰이지 않습니다. 그럼 어디에 쓰이냐?
바로, 대칭키를 안전하게 공유할 때 사용됩니다.
- 클라이언트는 대칭키의 재료인 Pre-Master Key를 서버의 공개키로 암호화해서 서버로 보내고
- 서버는 비공캐기로 이 암호화된 Pre-Master Key를 복호화해서 이 값을 얻습니다.
이 과정을 통해
- 키를 노출시키지 않고,
- 클라이언트와 서버는 "같은 비밀인 Pre-Master Key"를 갖게 되고,
- 거기서 같은 대칭키를 만들어냅니다.
이제 키들이 어떤 역할을 하는지 이해가 되셨죠? 이제 진짜로 TLS Handshake 흐름 전체를 따라가 볼 차례입니다.
TLS 연결 과정
HTTPS에서 TLS는 서버와 클라이언트가 암호화 통신을 시작하기 전, 서로 정보를 교환하면서 신뢰할 수 있는 보안 연결을 맺는 과정을 수행합니다. → 이게 바로 TLS Handshake입니다.
0. www.example.com 접속
1. ClientHello : "나 암호화 통신 하고 싶어요"
클라이언트는 접속한 후 먼저 서버에 ClientHello메시지를 보냅니다. 이 메시지에는
- 클라이언트가 지워나는 TLS버전
- 사용할 수 있는 암호화 알고리즘 리스트
- 랜덤한 값
- (필요 시) 세션 재사용을 위한 세션 ID
가 포함되어 있습니다.
이 단계에서는 클라이언트가 서버에게 "나 이런 환경으로 암호화할 수 있어요!" 라고 말하는 셈입니다.
2. ServerHello + 인증서 : "좋아, 그럼 내 정보는 이거야"
서버는 이에 응답하며 클라이언트에게 ServerHello 메시지를 보냅니다. 이 안에는
- 선택된 TLS 버전과 암호화 알고리즘
- 랜덤한 값
- 서버의 인증서 (이 안에 공개키가 들어있음)
이런 정보가 포함됩니다.
이 인증서가 앞에서 설명한 X.509 인증서, 신뢰할 수 있는 CA로부터 발급된 전자 신분증입니다.
3. 클라이언트가 Pre-Master Key 생성 + 공개키로 암호화
이제 클라이언트가 진짜 중요한 작업을 합니다.
- 랜덤한 Pre-Master Key를 생성하는데, 이건 자신만이 아는 비밀값입니다.
- 서버가 준 인증서 내 공개키로 이 값을 암호화하고,
- 암호화된 값을 서버로 전송합니다.
이 부분이 바로 서버 내 비대칭키의 쓰임 포인트입니다. 누구나 서버의 공개키로 암호화를 시도할 수 있지만, 복호화는 서버만 가진 비공개키로만 가능하기 때문에 안전하게 복호화가 가능합니다.
4. 서버가 비공개키로 복호화 → Pre-Master Key 획득
서버는 클라이언트가 보낸 암호화된 데이터를 자신의 비공개키로 복호화해서 Pre-Master Key를 획득합니다.
이 순간, 서버와 클라이언트는 같은 Pre-Master Key를 갖게 된 상태가 됩니다.
5. 세션키 (대칭키) 파생
이제 클라이언트와 서버는 같은 Pre-Master Key와 서로 교환했던 ClientRandom + ServerRandom값을 가지고 있죠? 이걸 PRF(Pseudo-Random Function)라는 함수에 넣어서 서로 같은 대칭 세션 키를 계산하게 됩니다.
그리고 이 대칭키가 실제로 데이터를 암호화/복호화할 때 사용되는 것이죠.
즉, HTTPS가 안전한 이유는, 서버와 클라이언트가 같은 "대칭키"를 공유한 상태에서만 통신을 시작하기 때문입니다.
→ TLS Handshake 끝!
그럼 그 이후 통신은 어떻게 될까요?
Handshake 이후에는 모든 HTTP 요청/응답 데이터를 이 세션 키로 암호화합니다.
클라이언트:
GET /home HTTP/1.1
Host: example.com
→ 세션 키로 암호화 → 서버로 전송
서버:
HTTP/1.1 200 OK
Content-Type: text/html
→ 세션 키로 암호화 → 클라이언트로 전송
이제 서버와 클라이언트는 같은 세션 키(대칭 키)를 공유하게 되었고, 서로의 데이터를 암호화해서 안전하게 주고받을 수 있게 됩니다.
실제 데이터 송수신에서 HTTPS는 어떻게 데이터를 주고받을까
이제 서버와 클랑이너트는 TLS Handshake를 통해 서로 같은 세션키인 "대칭키"를 가지게 되었습니다. 이제 HTTP 요청/응답이 시작되겠죠? 하지만 이 모든 데이터는... 외부에서 절대로 읽을 수 없도록 완전히 암호화된 상태로 전송됩니다.
자, 그럼 HTTPS가 실제로 어떻게 데이터를 송수신하는지, 차근차근 봅시다.
HTTPS에서 사용하는 암호화는 다음과 같은 방식으로 이루어집니다.
- 대칭키를 이용해서
- HTTP 메시지 전체를 암호화합니다. (헤더 + 본문 포함)
- MAC(Message Authentication Code) 또는 AEAD 기법으로 무결성도 함께 보호합니다.
클라이언트 → 서버 요청
🔓 원래 요청:
GET /login HTTP/1.1
Host: example.com
Cookie: session=abcd1234
🔒 HTTPS에서는?
[TLS Record] {
Content-Type: application data
Encrypted Data: [완전한 암호화 내용]
}
브라우저 개발자 도구 → 네트워크 탭을 열어보면, HTTPS 통신에서는 실제 요청 내용을 볼 수 없고, 암호화된 바이너리 형태만 확인됩니다.
또한, 단순히 "암호화"만 하는 게 아닌, "무결성 검증"도 함께 수행합니다. 중간에 누군가 몰래 데이터를 바꿔도 이를 감지할 수 있도록 하는 것이죠. 이건 버전마다 다른데,
TLS 1.2에서는
- MAC 키로 HMAC을 만들어 데이터에 함께 붙이고
- 수신 측에서는 같은 MAC키로 HMAC을 계산해서 비교합니다.
TLS 1.3에서는
- AEAD (Authentication Encryption with Associated Data) 방식을 사용하고,
- 암호화 + 무결성 검사를 한 번에 처리합니다. → 더 빠르고 안전하죠.
HTTPS는 한 번 연결을 맺으면, 그 대칭키를 바탕으로 여러 개의 요청/응답을 암호화해서 교환할 수 있습니다. 쿠키, 로그인 정보, API 호출 등 모든 통신이 대칭키로 암호화되고, MAC 또는 AEAD로 무결성까지 검증됩니다. 그 결과, 데이터가 노출되거나, 중간에 조작되거나, 위조되는 것을 막을 수 있는 것입니다.
사용자 입장에서 HTTPS가 주는 이점
- 로그인할 때 비밀번호가 중간에서 유출될 걱정이 없음.
- 결제 정보를 입력해도 누가 볼 수 없음
- DNS 스푸핑, 패킷 변조 공격(MITM)을 막을 수 있음.
- 브라우저에서 "자물쇠 표시"로 안전함을 확인할 수 있음.
HTTPS는 TLS Handshake로 만들어진 세션 키를 기반으로 서버-클라이언트가 주고받는 모든 데이터를 암호화 + 무결성 보호하며 전송합니다. 이로써 HTTPS는 보안, 신뢰성, 데이터 보호를 한 번에 달성하는 보안의 핵심 기술입니다 :)
'네트워크' 카테고리의 다른 글
Socket이 뭘까? WebSocket과 Socket.io 알아보기 (2) | 2024.11.13 |
---|---|
SSH에 대해 알아보자. (0) | 2024.10.19 |
Polling과 SSE, 실시간 통신에서 무엇이 더 적합할까? (1) | 2024.10.18 |