HTTPS

mongBrown·2026년 4월 29일

HTTPS는 어떻게 안전한 통신을 보장할까

브라우저 주소창에 https://google.com을 입력하는 순간, 수많은 패킷이 인터넷을 가로질러 오간다. 그 경로 어딘가에서 누군가 패킷을 가로챈다면 어떻게 될까.

HTTPS는 이 문제를 해결하기 위해 존재한다. 그리고 HTTPS가 동작하려면 먼저 두 가지 암호화 방식을 이해해야 한다.


대칭키 암호화

대칭키 암호화는 암호화와 복호화에 동일한 키 하나를 사용하는 방식이다. 자물쇠에 비유하면, 잠글 때도 열 때도 같은 열쇠를 쓰는 것과 같다.

[송신측]  평문 + 대칭키 → 암호문 전송
[수신측]  암호문 + 대칭키 → 평문 복원

같은 키로 암호화와 복호화를 처리하기 때문에 연산 구조가 단순하다. 그래서 속도가 빠르고 대용량 데이터 암호화에 적합하다. 단, 양쪽 모두 같은 키를 가지고 있어야 동작한다.


비대칭키 암호화

비대칭키 암호화는 공개키(Public Key)비밀키(Private Key) 두 개의 키를 한 쌍으로 사용한다. 공개키로 암호화한 것은 비밀키로만 복호화할 수 있다.

[공개키]  누구에게나 공개해도 된다
[비밀키]  절대 외부로 노출하지 않는다
[송신측]  평문 + 수신측 공개키 → 암호문 전송
[수신측]  암호문 + 수신측 비밀키 → 평문 복원

공개키는 누가 가져가도 상관없다. 그 키로 암호화한 내용은 비밀키를 가진 사람만 풀 수 있기 때문이다. 비밀키는 서버 안에서만 존재하고 네트워크를 통해 절대 전송되지 않는다.

다만 대칭키 대비 연산 비용이 크다. 수백 배 느리기 때문에 대용량 데이터를 매번 비대칭키로 암호화하면 성능 문제가 생긴다.


HTTPS에서 두 방식을 어떻게 쓸까

브라우저와 서버 사이를 오가는 데이터를 암호화하려면 빠른 대칭키가 적합하다. 그런데 대칭키를 쓰려면 브라우저와 서버가 먼저 같은 키를 가지고 있어야 한다.

문제는 그 키를 어떻게 공유하느냐다. 인터넷을 통해 키를 보내면 중간에 탈취당할 수 있다.

graph LR
    B[브라우저] -- "대칭키를 그냥 전송?" --> 공격자
    공격자 -- "탈취 가능" --> S[서버]

여기서 비대칭키를 활용하면 이 문제를 해결할 수 있다. 대칭키 자체를 서버의 공개키로 암호화해서 전달하면, 서버의 비밀키를 가진 서버만 그 대칭키를 풀 수 있다.

sequenceDiagram
    participant B as 브라우저
    participant S as 서버

    S->>B: 서버 공개키 전송 (탈취당해도 OK)
    Note over B: 세션키(대칭키) 생성
    B->>S: 세션키를 서버 공개키로 암호화해서 전송
    Note over S: 서버 비밀키로 복호화 → 세션키 획득
    Note over B,S: 이후 통신은 세션키(대칭키)로 암호화

비밀키는 서버 밖으로 나간 적이 없다. 네트워크 구간에서 탈취될 일이 없다.

결국 비대칭키는 대칭키를 안전하게 교환하는 데만 쓰고, 실제 데이터 통신은 빠른 대칭키로 처리한다. 두 방식의 장점만 취하는 방식이다.


서버를 어떻게 믿나 — CA와 인증서

비대칭키로 세션키 교환 문제는 해결됐다. 그런데 한 가지 문제가 남아있다.

서버가 공개키를 보내면서 "나 google.com이야"라고 주장한다고 해보자. 공격자도 똑같이 공개키를 만들어서 "나 google.com이야"라고 할 수 있다. 공개키 자체로는 신원을 증명하지 못한다.

여기서 CA(Certificate Authority, 인증 기관) 가 필요하다. DigiCert, Let's Encrypt 같은 공인된 제3자 기관이다.

CA는 어떻게 신원을 보증하나

서명(Signature)이라는 개념이 핵심이다. 암호화와 방향이 반대다.

암호화:  공개키로 잠그고  → 비밀키로 열어
서명:    비밀키로 서명하고 → 공개키로 검증

CA가 서버 인증서에 CA 비밀키로 서명을 남긴다. 그 서명은 CA 공개키로만 검증할 수 있다. 공격자가 가짜 인증서를 만들어도 CA 비밀키가 없으면 서명이 맞지 않아 검증에 실패한다.

sequenceDiagram
    participant G as google.com 서버
    participant CA as CA (DigiCert 등)
    participant B as 브라우저

    G->>CA: 내 공개키 인증해줘
    Note over CA: google.com 신원 확인
    CA->>G: CA 비밀키로 서명한 인증서 발급

    B->>G: https 접속 요청
    G->>B: 인증서 전송 (서버 공개키 + CA 서명 포함)
    Note over B: 브라우저 내장 CA 공개키로 서명 검증
    Note over B: 검증 성공 → 진짜 google.com

브라우저는 신뢰할 수 있는 CA 목록과 각 CA의 공개키를 설치 시점에 내장하고 있다. CA 서버에 실시간으로 접속할 필요 없이 로컬에서 검증이 완결된다. CA 공개키는 도메인 단위가 아니라 CA 기관 단위로 브라우저에 저장된다.

브라우저 내장 CA 목록
├── DigiCert 공개키
├── Let's Encrypt 공개키
├── GlobalSign 공개키
└── ...

TLS 핸드셰이크 — 전체 흐름

지금까지 설명한 과정이 HTTPS 통신에서 실제로 어떻게 순서대로 동작하는지 보면 이렇다.

sequenceDiagram
    participant B as 브라우저
    participant S as google.com 서버

    Note over B,S: 1단계 — TCP 3-way handshake
    B->>S: SYN
    S->>B: SYN-ACK
    B->>S: ACK

    Note over B,S: 2단계 — TLS 핸드셰이크
    B->>S: Client Hello (지원하는 암호화 방식 목록)
    S->>B: Server Hello + 인증서 전송 (서버 공개키 포함)
    Note over B: CA 공개키로 인증서 서명 검증
    Note over B: 세션키(대칭키) 생성
    B->>S: 세션키를 서버 공개키로 암호화해서 전송
    Note over S: 서버 비밀키로 복호화 → 세션키 획득
    B->>S: Finished (세션키로 암호화)
    S->>B: Finished (세션키로 암호화)

    Note over B,S: 3단계 — 실제 데이터 통신
    B->>S: HTTP 요청 (세션키로 암호화)
    S->>B: HTTP 응답 (세션키로 암호화)

TCP 3-way handshake로 연결 가능 여부를 먼저 확인하고, 그 위에서 TLS 핸드셰이크가 진행된다. 인증서 검증과 세션키 교환이 끝나야 비로소 실제 데이터 통신이 시작된다. 우리가 매일 쓰는 HTTPS가 이 구조 위에서 동작한다.

profile
화이팅!

0개의 댓글