144. 키 파생 함수 (KDF)와 TLS 1.3의 HKDF
⚠️ 이 문서는 "해커 몰래 교환한 1개의 비밀 씨앗(Shared Secret)만으로 어떻게 암호화, 서명, 검증 등 용도가 다른 수십 개의 안전한 마스터키들을 뽑아낼 것인가?"라는 암호 공학의 가장 실무적이고 거대한 파이프라인이자, 현존 최고의 인터넷 표준인 TLS 1.3의 심장 박동기인 HKDF의 실제 구현을 다룹니다.
핵심 인사이트 (3줄 요약)
- 본질: KDF(Key Derivation Function)는 밍밍하고 길이가 안 맞는 하나의 원본 난수를 해시 믹서기에 넣고 돌려서, 통신에 필요한 정해진 길이의 강력하고 무작위적인 여러 개의 비밀키(예: AES-256 키)들을 뽑아내는(Derive) 암호학적 정수기이자 뻥튀기 기계다.
- 가치: 대칭키는 "무엇(데이터)을 암호화하는가" 못지않게 "어디서(키의 질) 튀어나왔는가"가 보안을 결정한다. KDF를 거친 키들은 우연히 부딪히거나 유추될 확률(키 노출)이 0%로 수렴하여 수학적 완벽성(Domain Separation)을 제공한다.
- 융합: TLS 1.3은 과거 버전의 누더기 같던 키 파생 방식을 싹 다 버리고, 오직 2단계 구조(Extract로 농축하고, Expand로 뻥튀기)를 가진 HKDF(HMAC-based KDF) 단일 표준 아키텍처 하나만으로 수십 개의 통신 터널 키를 융합/통제하는 극한의 모듈화를 달성했다.
Ⅰ. 개요 및 왜 KDF가 필수적인가? (Context & Necessity)
우리는 앨리스와 밥이 ECDHE 핀볼 게임(타원곡선)으로 18F9A... 라는 똑같은 찌꺼기 번호(Shared Secret)를 맞추는 것을 보았다.
초보 개발자는 이 찌꺼기 번호를 그대로 AES(키=찌꺼기, 평문=영화)로 써서 암호화하려 든다.
이것은 자살 행위다.
- 재사용의 저주: 브라우저와 서버는 데이터를 가리는 '암호화용 키($K_{enc}$)'와 해커가 고쳤는지 확인하는 '도장용 키($K_{mac}$)'를 따로 써야 한다. 찌꺼기 번호 하나로 암호화도 하고 도장도 찍으면 수학의 상호 간섭이 일어나 해커가 역산으로 키를 뚫어버린다.
- 지저분한 품질 (엔트로피 부족): 핀볼 게임 결과물인 X좌표 값은 어떤 수학적 패턴(예: 0이 연달아 나오는 구간 등)을 띨 수도 있다. 해커가 이 패턴을 힌트 삼아 무차별 대입 공격(Brute Force)을 시도하면 공격 반경이 확 줄어든다.
그래서 암호학의 법률은 명시했다. "원석(Shared Secret)을 그대로 쓰지 마라. 무조건 KDF(키 파생 믹서기)에 넣고 소금(Salt)을 쳐서 완벽하게 랜덤한 맑은 물(난수)로 정수(Derive)시킨 뒤, 가위로 잘라서 용도별로 나눠 써라!"
📢 섹션 요약 비유: 땅에서 캔 '원유(Shared Secret)'를 자동차 엔진(AES)에 그냥 부으면 차가 폭발합니다. 원유를 정유 공장(KDF)에 가져가서 펄펄 끓여 불순물을 날리고(추출), 경유(암호화 키), 휘발유(MAC 키), 등유(다음 세션 키)로 쫙쫙 분류해서(확장) 뽑아내야만 기계들이 폭발 없이 완벽하게 돌아갑니다.
Ⅱ. TLS 1.3의 심장: HKDF-Extract와 Expand의 2단 콤보
과거 TLS 1.2는 PRF(Pseudo-Random Function)라는 다소 복잡한 방식을 썼지만, TLS 1.3은 이를 더 우아하게 추상화한 HKDF (HMAC-based KDF) 하나로 천하를 통일했다. HKDF는 앞서 [136번 문서]에서 배운 것처럼 철저한 2단계(Extract $\rightarrow$ Expand)로 동작한다.
1단계: 용광로 농축 (HKDF-Extract)
- 투입: 덜 섞인 ECDHE 찌꺼기(IKM, 원석)와 양쪽 컴퓨터에서 굴린 신선한 난수 소금(Salt = Client Random + Server Random)을 HMAC 믹서기에 때려 넣는다.
- 작동: 윙윙 돌려 불순물(수학적 패턴)을 완전히 으깨버린다.
- 결과물: 우주에서 가장 완벽한 100% 무작위 난수 원액인 마스터 시크릿 (PRK, Pseudo-Random Key) 하나가 툭 떨어진다. (엄청나게 찐득한 황금빛 원액이다.)
2단계: 용도별 뻥튀기 (HKDF-Expand)
- 투입: 방금 만든 마스터 원액(PRK)을 다시 HMAC 믹서기에 넣는다. 이때, 믹서기에 물을 타는데, 그냥 물이 아니라 꼬리표(Label,
Info)를 붙인 물을 탄다. - 꼬리표의 마법 (Domain Separation):
Info = "client handshake traffic secret"을 넣고 믹서기를 돌리면 $\rightarrow$ 클라이언트 전용 256비트 AES 키가 줄줄 나온다.Info = "server handshake traffic secret"을 넣고 믹서기를 돌리면 $\rightarrow$ 서버 전용 256비트 AES 키가 줄줄 나온다.Info = "resumption master secret"을 넣고 돌리면 $\rightarrow$ 내일 재접속(0-RTT)할 때 쓸 임시 티켓 번호가 나온다.
- 결과물: 마스터 원액 1방울에서, 내가 원하는 길이의 완벽하게 독립적인 열쇠 수십 개가 끝도 없이 뽑혀 나온다!
┌──────────────────────────────────────────────────────────────────────────────┐
│ TLS 1.3 핸드셰이크 내부의 HKDF 파이프라인 시각화 │
├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ [ 1. 원석 캐기 ] │
│ ECDHE로 만든 "Shared Secret" (찌꺼기 덩어리) │
│ │ │
│ ▼ │
│ [ 2. Extract 공장 (용광로) ] │
│ │ ◀── (서버/클라이언트의 신선한 Random 난수 소금) │
│ [ HMAC-SHA256 믹서기 가동 🌪️ ] │
│ │ │
│ ▼ │
│ ★ [ PRK (마스터 시크릿 원액) ] ★ │
│ │
│ [ 3. Expand 공장 (수도꼭지 분배) ] │
│ ┌────────┴────────┬───────────────┐ │
│ ▼ ▼ ▼ │
│ (Info="C_KEY") (Info="S_KEY") (Info="MAC_KEY") │
│ [ HMAC 믹서기 ] [ HMAC 믹서기 ] [ HMAC 믹서기 ] │
│ ▼ ▼ ▼ │
│ 클라이언트 암호용 서버 암호용 도장 찍기(인증)용 │
│ AES-256 키 AES-256 키 HMAC-SHA 키 │
│ │
│ * 핵심: 꼬리표(Info)가 1글자만 달라도 믹서기가 완전히 다른 키를 뱉어내므로, │
│ 서로 다른 용도의 키 3개가 우연히 똑같아져서(충돌) 해킹당할 확률은 0%다! │
└──────────────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 클라이언트(나)의 컴퓨터와 서버(네이버)의 컴퓨터가 각자 자기 뱃속에서 이 HKDF 공장을 동시에 돌린다. 둘 다 똑같은 원석, 똑같은 소금, 똑같은 꼬리표 문자를 믹서기에 넣었기 때문에, 각자 1,000km 떨어져 있어도 서로의 화면에는 1비트의 오차도 없이 완벽하게 똑같은 [암호화 키]와 [도장 키]가 세트로 톡 떨어지는 암호학의 가장 거대한 카타르시스가 완성된다.
- 📢 섹션 요약 비유: 콜라 원액 1방울(Shared Secret)을 물(Salt)과 섞어서 거대한 콜라 통(PRK 마스터)을 만듭니다. 그리고 "얼음 컵(클라이언트 암호용)", "종이컵(서버 암호용)", "캔(도장용)"에 콜라를 쫙쫙 나눠 담습니다(Expand). 컵의 모양(Info)이 다르면 맛의 느낌도 완전히 달라져서 도둑이 컵 하나를 훔쳐 마셔도 다른 컵의 맛을 절대 유추할 수 없는 마법의 디스펜서(자판기)입니다.
Ⅲ. 실무적 의의: 암호의 오남용(Key Reuse) 원천 차단
과거 해킹 역사에서 가장 뼈아픈 실수 중 하나는 "키 재사용(Key Reuse)"이었다. 암호화(AES) 할 때 쓰던 비밀키를, 무결성 도장(HMAC) 찍을 때 또 갖다 쓴 것이다. 해커는 이 두 가지 방정식이 똑같은 미지수(Key)를 쓴다는 점을 노려 연립방정식을 풀듯 역산해 냈고, 며칠 만에 은행 서버의 마스터키가 털려버렸다.
HKDF의 철학은 '도메인 분리(Domain Separation)'다.
HKDF-Expand 단계에서 Info 파라미터로 "이건 무조건 암호화 전용 키야", "이건 무조건 도장 전용 키야"라고 라벨을 붙여버리면, 수학적으로 두 키는 아무런 연관성을 가지지 않는 남남이 되어버린다. 개발자가 바보같이 코딩해서 똑같은 키를 여러 군데 재사용하려 해도, 시스템이 알아서 분리수거된 키를 쥐여주어 해커의 역산 공격을 원천적으로 막아(Fool-proof)버린다.
Ⅳ. 결론
"재료의 퀄리티가 요리의 끝을 결정한다." 아무리 강력한 AES-256 자물쇠와 튼튼한 RSA 인증서를 달아놔도, 그 자물쇠에 끼우는 쇳조각(Key) 자체가 무른 진흙(엔트로피 부족)이거나 옆집 자물쇠랑 똑같은 쇳조각(키 재사용)이라면 시스템은 1초 만에 붕괴한다. HKDF(키 파생 함수)는 덜 정제된 비밀 씨앗을 가장 날카롭고 무자비한 100% 난수 열쇠 다발로 연마하여 뿌려주는 대장간이다. TLS 1.3이 현대 인터넷의 절대 방벽이 된 이유의 8할은 이 우아하고 빈틈없는 HKDF 아키텍처에 빚을 지고 있다.
📌 관련 개념 맵
- 전체 분류: KDF (Key Derivation Function, 키 도출/파생 함수)
- 표준 기술 규격: RFC 5869 (HMAC-based Extract-and-Expand Key Derivation Function)
- 현대 인터넷 응용: TLS 1.3의 Key Schedule (마스터키 생성 메커니즘 전반)
- 보안 달성 목표: 도메인 분리 (Domain Separation, 용도별 키 독립성 보장), 엔트로피(무작위성) 증대
👶 어린이를 위한 3줄 비유 설명
- 철수와 영희가 흙 속에서 반짝이는 비밀의 돌멩이(원석) 하나를 같이 주웠어요. 하지만 돌멩이 그대로는 자물쇠에 넣을 수가 없었죠.
- 그래서 'HKDF'라는 마법의 자판기에 돌멩이와 소금을 넣고 버튼을 꾹! 누르니까(Extract), 돌멩이가 녹아서 맑은 황금빛 원액 하나가 탄생했어요.
- 자판기에서 "암호화용!", "도장용!" 버튼을 또각또각 누르니까(Expand), 아까 그 원액 하나로 모양과 쓰임새가 완벽하게 다르고 절대 서로 안 겹치는 튼튼한 황금 열쇠 10개가 툭 튀어나와서 암호 세팅이 끝났답니다!