요약

  • HKDF의 솔트는 일반적으로 비밀이 아닙니다. 솔트는 사용 사례를 분리하고 독립성을 뒷받침함으로써 추출 단계를 강화할 수 있지만, 엔트로피를 만들어내거나 입력을 인증하거나 비밀번호 추측 비용을 높이는 역할은 하지 못합니다.
  • info입력은 다른 역할을 담당합니다. 즉, 확장된 키를 프로토콜, 버전, 역할, 트랜스크립트 또는 용도에 결합하는 것입니다. 도출이 성공했다고 신뢰할 수 있는 것은 입력·솔트·인코딩된 컨텍스트·출력 역할의 출처가 그대로 보존될 때뿐입니다.

동일한 두 비밀이 서로 다른 방으로 들어가는 일

하나의 공유 비밀을 받아 세 가지 출력이 필요한 서비스를 상상해 보십시오. 암호화 키, 초기화 벡터, 헤더 보호 키입니다. 팀은 같은 바이트를 같은 KDF에 세 번 입력합니다. 호출은 성공하고 길이도 적절해 보이며 양쪽 엔드포인트가 일치합니다. 그러나 호출에 서로 다른 컨텍스트가 담겨 있지 않다면, 이 서비스는 어떤 출력이 어떤 역할에 속하는지 확립하지 못한 것입니다. 바이트를 만들었을 뿐, 방어 가능한 키 스케줄을 만든 것이 아닙니다.

이것이 "비밀을 해시하라"는 무심한 표현 뒤에 숨어 있는 실질적 문제입니다. 키 도출은 단순히 문자열을 무작위처럼 보이게 만드는 방법이 아닙니다. 명시된 가정 아래에서 소스 재료를 변환한 뒤, 알고리즘·프로토콜 버전·방향·수명 주기에 걸쳐 출력들을 서로 분리해 두어야 합니다.

Hugo Krawczyk은 HKDF 설계와 그 분석을 통해 이 구분을 내구성 있는 형태로 정립했습니다. Pasi Eronen과 공동 집필한 RFC 5869는 이 패턴을 추출 후 확장(extract-then-expand)이라고 부릅니다. Krawczyk의 기반이 되는 논문은 그 형식적 근거를 제공합니다. 먼저 균일하지 않을 수 있는 입력 재료로부터 의사난수 키를 얻고, 그다음 그 키를 사용해 응용이 필요로 하는 특정 출력들을 만들어냅니다. IETF 기록은 Krawczyk를 HKDF가 사용하는 프리미티브인 HMAC의 공동 저자로도 남기고 있습니다. ACM의 2025년 시상 기록은 보안 통신의 기초 이론과 배포된 프로토콜에 관한 그의 폭넓은 업적을 인정했습니다. 이 약력이 여기서 중요한 이유는 단 하나입니다. 어떤 설계 결정이 이토록 멀리까지 전파되었는가 하는 점, 즉 키 스케줄의 중간 단계는 자체적인 경계를 갖자는 결정입니다.

추출은 생성이 아닙니다

HKDF-Extract는salt와 초기 키 재료(IKM) 두 입력을 받아 의사난수 키(PRK)를 반환합니다:

PRK = HMAC-Hash(salt, IKM)

이 연산은 엔트로피 생성기가 아니라 추출기입니다. IKM이 흩어져 있는 불확실성을 담고 있다면, 추출은 이를 HMAC 키로 적합한 고정 길이 값으로 응집할 수 있습니다. 그러나 원래 없던 불확실성을 더할 수는 없습니다. 모든 그럴듯한 IKM을 저비용으로 열거할 수 있는 공격자는 모든 추측에 대해 동일한 추출을 실행할 수 있습니다.

이 구분은 Diffie–Hellman에서 구체적으로 드러납니다. 공유된 군 원소는 일반적으로 이미 균일한 의사난수 HMAC 키로 모델링되지 않으므로, RFC 5869는 Diffie–Hellman 값에 대해 추출 단계를 생략해서는 안 된다고 말합니다. 반대로 이미 강한 의사난수 키인 입력은 때때로 확장으로 바로 갈 수 있습니다. 따라서 "때때로 생략 가능"은 IKM의 소스 분포와 표현에 관한 진술이지, 벤치마크가 느리다는 이유로 뒤집는 최적화 스위치가 아닙니다.

NIST SP 800-56C Rev. 2도 키 설정을 위해 같은 아키텍처 어휘 — 추출, 확장, 추출 후 확장 — 를 사용합니다. 이러한 더 넓은 표준화는 유용한 증거입니다. 이 경계는 특정 구현의 외관적 명명이 아니라, 키가 목적을 갖기 전에 무엇이 확립되었고 무엇이 확립되지 않았는지를 서술하는 방식입니다.

공개 솔트가 여전히 중요한 이유

RFC 5869에서 솔트는 선택 사항이며 일반적으로 비밀이 아닙니다. 생략될 때 HKDF는 해시 길이와 같은 길이의 0 옥텟 문자열로 대체합니다. 프로토콜은 솔트를 평문으로 전송하거나, 인증된 공개 논스로부터 도출하거나, 또 다른 키처럼 꾸미지 않고 적절한 고정 값을 재사용할 수 있습니다.

공개라는 것이 쓸모없다는 뜻은 아닙니다. 잘 선택된 솔트는 추출의 분석적 기반을 강화하고, 해시 함수의 서로 다른 사용을 독립적으로 만들 수 있으며, 소스 독립적 추출을 뒷받침합니다. 제한된 엔트로피를 지닌 솔트조차 도움이 될 수 있습니다. 그 이득은 공격자가 읽을 수 없다는 데서 오지 않습니다.

반대로 비밀이 아니라는 것이 "누구나 선택할 수 있다"는 뜻도 아닙니다. RFC 5869의 독립성 지침은 솔트가 IKM과 독립적이어야 한다고 말합니다. 프로토콜이 논스로 솔트를 만든다면, 그 논스는 적대적 선택에 대해 인증되어야 합니다. 따라서 운영 기록은 대시보드가 자주 하나로 묶어버리는 네 상태를 구분해야 합니다: 솔트 부재, 고정 프로토콜 솔트, 새로 인증된 공개 솔트, 공격자 영향을 받은 솔트. 네 값 모두 노출될 수 있습니다. 그러나 동일한 보증을 담지 않습니다.

RFC 8188은 명확한 실배포 사례를 제공합니다. 이 표준의 HTTP 암호화 콘텐츠 인코딩은 전송된 솔트를 HKDF-Extract로 넣고, 콘텐츠 인코딩을 지명하는 고정 문자열은 확장을 위한info로 들어갑니다. 두 값이 공존하는 이유는 가시성이 구별 기준이 아니기 때문입니다. 하나는 키 재료에서 PRK를 추출하는 데 참여하고, 다른 하나는 출력의 용도를 지명합니다.

솔트는 비밀번호 강화가 아닙니다

"솔트"라는 단어는 비밀번호 저장 분야에서도 쓰이기 때문에 위험한 범주 도약을 유발합니다. 그 환경에서 고유한 솔트는 사전 계산된 테이블을 무력화하고 동일한 비밀번호들을 분리하지만, 비밀번호 자체는 여전히 낮은 엔트로피 재료입니다. 방어자는 또한 의도적인 계산 비용이 필요합니다.

HKDF에는 내장 작업 계수도 없고 메모리 하드 단계도 없습니다. RFC 5869는 이를 직접 말합니다. 추출은 기존 엔트로피를 응집할 수는 있지만 증폭할 수 없으며, HKDF는 비밀번호 KDF에서 기대되는 속도 저하를 포함하지 않습니다. 사람의 비밀번호에 HKDF를 한 번 적용하면 출력이 키의 시각적 형태를 갖출 수 있지만, 오프라인 공격자에게는 여전히 저렴한 추측 함수를 남겨줍니다.

PBKDF2는 반복 횟수를 명시적 매개변수로 만듭니다. Argon2는 한 걸음 더 나아가 메모리 비용, 패스 수, 병렬성을 설계의 일부로 삼으며, 비밀번호 해싱에는 Argon2id가 권장됩니다. 이 메커니즘들은 약한 비밀번호를 마법처럼 강하게 만들지는 않지만, 추측을 검증하는 경제성을 바꿉니다. HKDF의 공개 솔트는 전혀 다른 보안 논거를 서비스합니다. 명사를 공유한다고 해서 통제 수단이 서로 교체 가능해지는 것은 아닙니다.

이 경계는 리뷰와 사고 대응에서 중요합니다. "솔트를 넣었습니다"는 충분한 답이 아닙니다. 리뷰어는 어떤 구성이 솔트를 사용했는지, 소스 재료가 무엇이었는지, 추측이 저렴한지, 어떤 비용 매개변수가 강제되었는지, 그리고 솔트에 요구되는 독립성이나 고유성이 실제로 유지되었는지를 물어야 합니다.

info는 키가 자기 역할을 배우는 곳입니다

추출 이후 HKDF-Expand는 PRK,info값, 요청된 길이를 받습니다. RFC 5869는info를 응용 및 컨텍스트 고유 정보로 기술합니다. 여기에는 프로토콜, 알고리즘, 식별자, 길이가 담길 수 있으며, 같은 IKM이 서로 다른 컨텍스트에 대해 구별 불가능한 재료를 산출하는 일을 막는 것이 목적입니다.

이 역할은 마음대로 솔트로 옮길 수 없습니다. 솔트는 추출을 형성하고,info는 확장 단계에서 사용 사례들을 분리합니다. RFC 5869는info를 우회하게 되는 경우 PRK를 최종 출력으로 직접 반환하는 것조차 권하지 않으며, 컨텍스트 재료를 대체물로 Extract에 추가하는 것도 권하지 않습니다. PRK는 유용한 중간 비밀이지, 역할이 이미 확립된 키가 아닙니다.

TLS 1.3은 이 분리를 와이어 수준 설계에서 가시화합니다.HKDF-Expand-Label은 레이블 앞에tls13을 붙이고 트랜스크립트 해시를 컨텍스트로 결합할 수 있습니다. 스케줄은finished,key,iv같은 이름으로 값을 도출합니다. 이 레이블들은 문서화 주석이 아닙니다. 암호 연산에 입력되는 인코딩된 값입니다.

QUIC은 TLS 1.3의 확장 구조를 재사용하되 자체 용도를 추가합니다. RFC 9001은quic key,quic iv,quic hp라는 서로 다른 레이블 아래에서 AEAD 키, IV, 헤더 보호 키를 도출하며, 이 레이블들이 QUIC과 TLS 사이의 분리를 제공한다고 명시합니다. 로깅 시스템이 "HKDF-SHA256 성공"만 기록한다면, 어떤 키가 존재하도록 의도되었는지 설명하는 증거를 버리는 셈입니다.

HPKE는 더욱 명시적입니다. LabeledExtract와 LabeledExpand 입력에는HPKE-v1문자열, 암호 스위트 식별자, 용도 레이블이 포함됩니다. 이는 비밀을 스킴, 버전, 선택된 알고리즘에 결합합니다. MLS는 자체MLS 1.0접두사와 레이블된 스케줄로 별도의 에포크 비밀을 도출합니다. 이들은 독립적인 프로토콜 설계이지 하나의 마스터 템플릿의 문법적 변형이 아닙니다. 공통 교훈은, 모든 참여자가 일관되게 인코딩하고 검증할 때에만 레이블이 보안 도메인의 일부가 된다는 점입니다.

하나의 도출을 위한 네 가지 영수증

방어 가능한 키 스케줄은 출력 지문 이상을 남겨야 합니다.

첫 번째 영수증은 소스 출처입니다. IKM이 인증된 Diffie–Hellman 교환, 무작위 키, 사전 공유 비밀, 비밀번호 또는 다른 도출에서 왔는지를 기록합니다. 이 입력들은 같은 바이트 길이를 갖지만 엔트로피와 공격자 통제 가정은 극적으로 다를 수 있습니다.

두 번째는 솔트 출처입니다. 정확한 바이트, 생성 규칙, 인증 상태, 재사용 정책, IKM과의 관계를 보존합니다. "공개"는 기밀성 진술이지 출처 진술이 아닙니다.

세 번째는 인코딩된 컨텍스트입니다. 확장에 도달한 정확한 레이블, 프로토콜/버전 접두사, 암호 스위트, 역할, 트랜스크립트 해시, 길이 인코딩을 저장합니다. 응용이 인쇄한 친근한 레이블만으로는 부족합니다. 모호한 연결이나 일관성 없는 정규화는 로그가 멀쩡해 보이는 동안 분리를 지워버릴 수 있습니다.

네 번째는 출력 보관입니다. 출력이 키, IV, 익스포터, 재개 비밀, 중간 PRK 중 무엇인지 지명하고, 소유자, 허용 연산, 에포크, 삭제 시점을 기록합니다. 올바른 키라도 잘못된 논스 정책 아래 사용되거나 생성 시점 이후 보존된다면 여전히 운영 실패입니다.

이 영수증들이 함께 있으면 결정론적 프리미티브가 오라클로 오해되는 일을 막습니다. 일치하는 출력은 두 구현이 동등한 알고리즘에 동등한 입력을 공급했다는 것을 보여줄 뿐입니다. 입력이 예측 불가능했는지, 피어가 인증되었는지, 컨텍스트가 의도된 것인지, 오래된 키가 파기되었는지는 증명하지 않습니다.

출처