LabHub

블로그

TLS/SSL과 PKI 완전 정복 — 핸드셰이크, 인증서 체인, 암호 스위트, 0-RTT, 그리고 양자내성암호 시대 (2025)

한국어English日本語

0. 자물쇠 하나의 무게

브라우저 주소창 왼쪽의 작은 자물쇠. 사용자는 보통 2초도 보지 않고 지나간다. 그런데 그 자물쇠 뒤에는:

브라우저가 매 HTTPS 요청마다 하는 일 — "처음 본 서버를 믿을 수 있는가?", "이 통신을 누군가 엿듣고 있지 않은가?", "이 패킷이 변조되지 않았는가?" — 이 세 질문의 답이 TLS 와 PKI 라는 거대한 체계에 있다.

이 글은 그 체계의 안쪽을 파헤친다. 자물쇠를 클릭했을 때 실제로 무슨 일이 벌어지는지, 왜 TLS 1.3 이 TLS 1.2 보다 2배 빠른지, 왜 Let's Encrypt 가 혁명이었는지, 그리고 왜 2024년부터 급하게 양자내성 암호를 배포해야 하는지.

1. TLS 가 해결하는 세 가지 문제

1.1 Confidentiality — 엿듣기 방지

평문 HTTP 는 공유 WiFi 에서 tcpdump 한 줄로 읽을 수 있다. 2010년 Firesheep 확장 프로그램이 페이스북 세션 쿠키를 그대로 훔쳐가며 HTTPS 의 필요성을 대중화했다.

해결: 대칭 암호화 (AES, ChaCha20). 클라이언트와 서버가 공유 키로 암호화.

1.2 Integrity — 변조 방지

중간자 (MITM) 가 "100원 송금" 을 "10000원 송금" 으로 바꾸면? 암호화만으로는 못 막는다 (운좋게 복호화 후 유효한 메시지가 되면 그대로 통과).

해결: MAC (Message Authentication Code) 또는 AEAD (Authenticated Encryption with Associated Data). AES-GCM, ChaCha20-Poly1305.

1.3 Authentication — 상대가 누구인지

"google.com" 에 접속했는데 실제로는 공격자의 서버면? 암호화도 무결성도 의미 없다.

해결: X.509 인증서 + PKI (Public Key Infrastructure). CA (Certificate Authority) 가 서버의 신원을 보증.

2. 비대칭 암호 — 공유 키 없이 비밀 만들기

2.1 문제: 첫 만남의 딜레마

두 사람이 처음 만나서 암호화 대화를 하려면 공유 키가 필요하다. 하지만 공유 키를 어떻게 주고받는가? 평문으로 보내면 도청됨.

2.2 Diffie-Hellman — 1976년의 기적

W. Diffie, M. Hellman, R. Merkle (2002년 Turing 상) 의 아이디어:

Alice                           Bob
공개값 g, p 공유 (p 는 큰 소수)

a = random()                    b = random()
A = g^a mod p                   B = g^b mod p
        A 전송 →
B 수신

shared = B^a mod p              shared = A^b mod p
       = g^(ab) mod p           = g^(ab) mod p

중간자는 A, B 를 볼 수 있지만 g^(ab) mod p 를 계산하려면 a 나 b 를 알아야 함 → 이산 로그 문제 (큰 수에서 불가능).

2.3 RSA — 1977년의 대안

R. Rivest, A. Shamir, L. Adleman:

공개키: (n, e)     (n = p*q, p,q 는 비밀 소수)
개인키: d          (d*e ≡ 1 mod φ(n))

암호화: c = m^e mod n
복호화: m = c^d mod n

도전: n 에서 p, q 를 구하려면 큰 수 인수분해 — 고전 컴퓨터로 불가능.

2.4 두 알고리즘의 공존

초기 TLS (1994-2010) 는 주로 RSA:

문제: Forward Secrecy 없음. 서버 개인키가 유출되면 과거 모든 세션 복호화 가능.

2010년 이후 DHE / ECDHE (Diffie-Hellman Ephemeral) 로 전환. 매 세션마다 임시 키 쌍 → 과거 세션 보호.

TLS 1.3 은 RSA key exchange 를 완전 제거. 오직 ECDHE 만 허용.

2.5 ECC — 더 적은 비트로 같은 안전

Elliptic Curve Cryptography (1985 제안, 2000년대 보급):

대칭 보안 비트RSA 키 크기ECC 키 크기
801024160
1283072256
25615360512

ECC 256 = RSA 3072 수준. 모바일/IoT 에서 특히 유리. 현대 TLS 는 ECC 가 기본.

3. TLS 1.2 핸드셰이크 — 2-RTT 의 춤

Client                              Server
ClientHello     (TLS version, cipher suites,  │    random, extensions)  │────────────────────────────────→│
  │                                  │
ServerHello     (chosen cipher, random)CertificateServerKeyExchange     (ECDHE params)ServerHelloDone  │←────────────────────────────────│
  │                                  │
ClientKeyExchange     (ECDHE public)ChangeCipherSpecFinished (encrypted)  │────────────────────────────────→│
  │                                  │
ChangeCipherSpecFinished (encrypted)  │←────────────────────────────────│
  │                                  │
Application Data (encrypted)  │←──────────────────────────────→│

핵심: 데이터 전송 전 2번의 왕복 (2-RTT) 필요. 100ms RTT 면 200ms 지연. 웹 페이지 로딩의 체감 병목.

3.1 Cipher Suite 의 해독

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 을 분해:

이 네 가지 조합의 수가 수백 개. "Null cipher" 나 "export-grade 40-bit" 같은 안전하지 않은 조합이 한동안 남아있었다 (FREAK, Logjam 공격의 근원).

3.2 TLS 1.2 의 약점

4. TLS 1.3 — 2018년의 대수술

4.1 설계 철학

"안전하지 않은 옵션을 제거 한다. 설정 실수의 여지를 없앤다."

4.2 1-RTT 핸드셰이크

Client                              Server
ClientHello    (key_share: ECDHE public,  │   supported_versions: [1.3])  │────────────────────────────────→│
  │                                  │
ServerHello    (key_share: ECDHE public){ EncryptedExtensions,Certificate,CertificateVerify,Finished }  │←────────────────────────────────│
  │                                  │
{ Finished }Application Data (encrypted)  │────────────────────────────────→│

핵심:

1 RTT 완료. TLS 1.2 대비 2배 빠름.

4.3 제거된 기능들

허용되는 cipher suite 는 단 5개:

TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_CCM_SHA256
TLS_AES_128_CCM_8_SHA256

잘못 설정할 여지가 구조적으로 없어짐.

4.4 0-RTT Resumption — 거의 즉시 재접속

(이전 세션 있음)
Client                              Server
ClientHello    (key_share, early_data)[Early Data: GET / HTTP/1.1]   │ ← 0-RTT 전송!
  │────────────────────────────────→│
  │                                  │
ServerHello{ Finished }  │←────────────────────────────────│

재접속 시 0 RTT 로 데이터 시작. 모바일 앱, SPA 에서 극적 체감.

4.5 0-RTT 의 Replay Risk

0-RTT 데이터는 forward secrecy 가 없고 replay 될 수 있다. 공격자가 녹화했다가 재전송 → 서버가 같은 요청 두 번 처리.

멱등한 요청 (GET) 에만 0-RTT 허용. POST 는 별도 정책. HTTP/3 에서는 서버가 replay 감지 윈도우 유지.

4.6 TLS 1.3 도입 속도

2018 RFC 8446 표준화 → 2020 까지 브라우저 대부분 지원 → 2024 현재 HTTPS 트래픽의 90%+ 가 TLS 1.3.

5. 인증서 체인 — "처음 본 서버를 믿는 방법"

5.1 체인의 구조

[Root CA: DigiCert Global Root CA]       ← 브라우저/OS 에 미리 내장
        (서명)
[Intermediate CA: DigiCert TLS RSA SHA256 2020 CA1]
        (서명)
[End-entity: google.com]                 ← 서버가 제시

브라우저는:

  1. 서버로부터 [google.com + Intermediate] 인증서 체인 수신.
  2. Intermediate 의 공개키로 google.com 서명 검증.
  3. Root CA 의 공개키로 Intermediate 서명 검증.
  4. Root CA 는 브라우저가 이미 신뢰하는 것 → 체인 완성.

5.2 인증서 안의 내용 (X.509)

Certificate:
    Version: 3
    Serial Number: 04:a2:...
    Signature Algorithm: sha256WithRSAEncryption
    Issuer: C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1
    Validity:
        Not Before: Jan 1 2025
        Not After:  Apr 1 2026     ← 수명
    Subject: C=US, O=Google LLC, CN=*.google.com
    Subject Public Key Info:
        Public Key Algorithm: rsaEncryption
        Public Key: <2048 bits>
    X509v3 Extensions:
        Subject Alt Name: DNS:*.google.com, DNS:google.com, ...
        Key Usage: Digital Signature, Key Encipherment
        Extended Key Usage: TLS Web Server Authentication
        Authority Information Access: OCSP - http://...
        Certificate Policies: 2.23.140.1.2.2 (Organization Validated)
    Signature: <Intermediate CA 의 서명>

5.3 CA 의 3가지 레벨

5.4 CA 의 신뢰는 어디서 오는가

루트 CA 는 브라우저/OS 에 하드코딩:

각 벤더가 자체 CA 심사 프로그램 운영. 까다로운 감사를 통과해야 추가됨.

5.5 유명한 CA 실패들

"CA 하나를 뚫으면 인터넷 전체" 라는 구조적 약점 → 다음 장의 혁신들.

6. 인증서 투명성 (CT) — 감시의 민주화

6.1 문제의 재확인

CA 가 악성/실수로 잘못된 인증서를 발급해도 피해자가 모른다. 자기 도메인의 가짜 인증서가 어딘가 돌아다녀도 검출 못 함.

6.2 CT 의 아이디어

"모든 새 인증서를 공개 로그 에 기록하자. 누구나 감시할 수 있게."

6.3 효과

6.4 crt.sh 의 재미있는 효과

자기 회사 도메인을 crt.sh 에 검색하면:

7. Let's Encrypt — HTTPS 의 민주화 (2016)

7.1 2015 이전의 현실

"HTTPS 쓰려면 연 수십 달러 + 매년 수동 갱신 + 설치 난이도" → 전체 웹의 30% 만 HTTPS.

7.2 Let's Encrypt 의 3가지 혁신

  1. 무료: 기부금 + 대기업 후원 (Mozilla, EFF, Akamai, Cisco 등).
  2. 자동화: ACME 프로토콜. certbot 명령 한 줄.
  3. 짧은 수명 (90일): 자동 갱신 강제 → 탈취된 키의 피해 최소화.

7.3 ACME 프로토콜

1. 계정 생성 (공개키 등록)
2. 주문: "example.com 에 대해 인증서 원함"
3. Challenge:
   - HTTP-01: http://example.com/.well-known/acme-challenge/{token} 에 특정 값 업로드
   - DNS-01: _acme-challenge.example.com TXT 에 특정 값 설정
4. 서버가 Challenge 검증
5. CSR 제출 → 인증서 발급

7.4 Let's Encrypt 의 수치

7.5 후발주자들

8. 인증서 취소 — 해결되지 않은 문제

8.1 취소가 왜 어려운가

인증서 발급 후 수명이 남았는데 키가 유출되면 → 취소해야 함. 하지만 어떻게 브라우저에 "이 인증서 믿지 마" 를 알리는가?

8.2 CRL (Certificate Revocation List)

CA 가 취소된 인증서 목록을 게시:

8.3 OCSP (Online Certificate Status Protocol)

매 연결 시 CA 의 OCSP 서버에 "이 인증서 유효?" 쿼리:

8.4 OCSP Stapling

서버가 주기적으로 OCSP 응답을 받아서 핸드셰이크에 포함 시킴:

8.5 실제 작동 방식 — 푸시 기반

크롬/파폭은 OCSP 대신 자체 "파일 푸시":

8.6 짧은 수명이 최선?

Let's Encrypt 의 90일 주기가 여기서도 타협책. "취소 시스템이 불완전하니, 차라리 자주 갱신하자". Apple 은 2022년 TLS 인증서 최대 수명을 398일 로 제한.

9. HSTS, HPKP, CAA — 추가 방어층

9.1 HSTS (HTTP Strict Transport Security)

헤더:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

의미: "이후 1년간 절대 HTTP 로 접속하지 마. 무조건 HTTPS."

preload: Chrome HSTS preload 리스트에 등록 → 브라우저가 출하될 때부터 알고 있음.

9.2 HPKP 의 실패

Public Key Pinning 은 "내 도메인은 이 공개키만 믿어". 잘못 설정 시 사이트가 영구 죽음 → 너무 위험.

2018년 Chrome 이 HPKP 폐기. CT 가 같은 문제를 더 안전하게 해결.

9.3 CAA (Certificate Authority Authorization)

DNS 레코드:

example.com. CAA 0 issue "letsencrypt.org"

의미: "이 도메인에 대해 Let's Encrypt 만 인증서 발급 가능. 다른 CA 는 거절해야 함."

CA 가 발급 전 CAA 체크 의무화 (2017년부터). 실수/악성 CA 의 오발급 방지.

10. TLS 공격사 — 유명한 버그들

10.1 Heartbleed (2014)

OpenSSL 의 heartbeat 확장 버그. 클라이언트가 "16바이트 보냈으니 16바이트 돌려줘" 라고 요청하면서 실제로는 1바이트만 보냄 → 서버 메모리에서 16바이트 읽어 반환 → 메모리 덤프 유출.

피해:

교훈: 오픈소스도 자금 없이는 보안 버그 쌓임 → Linux Foundation 의 Core Infrastructure Initiative 탄생.

10.2 BEAST (2011), POODLE (2014), Lucky 13 (2013)

CBC 모드의 patching 공격들. 순차적으로 cipher 위치가 무너지면서 AEAD (GCM) 로의 전환 이 가속화.

10.3 FREAK, Logjam (2015)

"export-grade 512-bit" 키 교환을 강제 다운그레이드하는 공격. 1990년대 미국 수출 규제의 유물이 15년 후 공격 벡터로 돌아옴.

교훈: 이전 모드 호환성을 남겨두면 공격자가 그 모드로 다운그레이드 시킴. TLS 1.3 이 과격하게 구식 제거한 이유.

10.4 DROWN (2016), Sweet32 (2016)

SSLv2 나 3DES 등 레거시 암호의 취약점을 이용. 아직도 일부 서버가 지원 → 현대 연결 공격 가능.

10.5 Raccoon (2020), ALPACA (2021)

TLS 1.2 의 마지막 공격들. TLS 1.3 에는 영향 없음. 업그레이드 동기.

11. 양자내성 암호 — 2024년의 긴급 사안

11.1 Harvest Now, Decrypt Later 위협

양자 컴퓨터가 2030년대 상용화될 가능성. Shor 의 알고리즘으로 RSA, ECC 모두 깨진다. 공격자는 지금 트래픽을 녹화 해두고 양자 컴퓨터 나올 때 복호화 할 수 있음.

"향후 30년간 비밀이어야 하는 데이터" (의료 기록, 국가 기밀) 는 지금 당장 양자 저항이 필요.

11.2 NIST PQC 표준화 (2024)

NIST 가 2016년 시작한 선정 프로세스의 결과 (2024 확정):

격자 기반 (lattice-based) 암호가 주력. 양자 컴퓨터에도 여전히 어려운 문제.

11.3 하이브리드 접근

기존 ECDH 와 새 Kyber 를 동시에 사용 → "둘 다 뚫려야 복호화 가능". 점진적 전환 전략.

key = HKDF(ECDH(x25519) || Kyber768)

11.4 Chrome 의 배포 (2024)

2024년 8월 Chrome 116+ 이 TLS 에 X25519Kyber768 하이브리드 기본 활성화:

Cloudflare, AWS 도 비슷한 시기에 도입. TLS 사상 가장 큰 변화 중 하나.

11.5 남은 과제

12. 실무 TLS — 점검표

12.1 서버 설정 (nginx 예시)

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 valid=300s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

12.2 진단 도구

12.3 성능 튜닝

12.4 모니터링

13. 마치며 — 자물쇠의 역사가 말해주는 것

1994년 Netscape 의 허술한 SSL 1.0 에서 시작된 여정은 :

그리고 2024년, 양자 컴퓨터라는 전혀 새로운 차원의 위협 때문에 전체 스택이 다시 움직이기 시작했다. 30년간 쌓인 인프라가 앞으로 10년 안에 양자 안전으로 재구축될 것이다.

자물쇠 아이콘 하나 뒤에는 이 모든 역사가 있다. 매번 HTTPS 연결할 때마다 수십 명의 수학자, 엔지니어, 표준화 위원회의 작업이 동시에 작동한다.

다음 글에서는 JavaScript 엔진의 내부 — V8 의 hidden classes, TurboFan 최적화, Inline cache, 가비지 컬렉터, 그리고 왜 for (let x of array)for (let i = 0; i < array.length; i++) 보다 때로는 빠른지 — 를 파볼 예정이다.

참고 자료

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다