HKDF로 마스터키 하나에서 용도별 서브키 갈라내기

웹 · 앱 개발4분 읽기

Argon2id로 마스터키를 파생하고 나면 그 32바이트를 곧바로 파일 암호화에 쓰고 싶어집니다. 하지만 하나의 키를 인증에도, 메타데이터 암호화에도, 파일 키 보관에도 함께 쓰는 것은 암호 설계에서 피해야 할 대표적인 실수입니다. 한 용도에서 생긴 미세한 약점이 다른 용도로 번지고 키를 회전하거나 일부만 무효화하기도 어려워집니다. Ciphek은 이 문제를 HKDF 도메인 분리로 풀었습니다.

키를 재사용하지 말라는 원칙

암호 시스템에는 "하나의 키는 하나의 목적에만"이라는 오래된 원칙이 있습니다. 같은 키로 서로 다른 알고리즘을 돌리거나 다른 맥락에서 재사용하면, 한쪽의 논스 관리 실수나 오라클이 다른 쪽의 비밀까지 위협할 수 있습니다. 그래서 마스터키는 최종 사용 키가 아니라 오직 파생의 씨앗으로만 다루는 것이 안전합니다. 씨앗에서 용도마다 다른 키를 뽑아내고 각 용도는 자기 키만 알게 만듭니다.

이 뽑아내는 작업에 쓰는 것이 HKDF입니다. HKDF는 고엔트로피 입력을 받아 원하는 만큼의 독립적인 파생 키를 만들어 주는 표준 함수로, 각 파생에 서로 다른 라벨(info)을 붙여 결과를 완전히 분리할 수 있습니다. 마스터키는 이미 Argon2id를 거친 고엔트로피 값이므로 HKDF의 입력으로 이상적입니다.

세 갈래로 나눈 서브키

Ciphek은 마스터키에서 HKDF-SHA-256으로 세 개의 서브키를 파생합니다. 첫째는 인증 서브키로, 서버에 패스워드를 직접 보내지 않고도 "이 사용자가 올바른 패스워드를 안다"는 것을 증명하는 HMAC 검증자로 씁니다. 둘째는 메타데이터 서브키로, 파일명과 태그 같은 메타데이터를 AES-GCM-256으로 암호화하는 데 씁니다. 셋째는 파일 래핑 서브키로, 파일마다 만드는 무작위 키를 AES-KW로 감싸 보관하는 데 씁니다.

각 파생에는 서로 다른 고정 라벨이 들어갑니다. 인증용, 메타데이터용, 파일 래핑용 라벨이 문자열로 명확히 구분되어 있어서 같은 마스터키에서 나왔어도 세 서브키는 서로를 계산해 낼 수 없는 독립적인 값이 됩니다. 이 도메인 분리 덕분에 인증 경로에서 무언가 새더라도 파일 암호화 키에는 영향이 없습니다.

꺼낼 수 없는 키로 다루기

서브키를 만들 때 한 가지를 더 지켰습니다. 파생된 키를 브라우저 밖으로 직렬화할 수 없는 non-extractable CryptoKey로 만들었습니다. Web Crypto API는 키를 실제 바이트로 노출하지 않고 핸들만 넘겨주는 모드를 지원하는데, 이렇게 하면 실수로 키를 로그에 남기거나 서버로 전송하는 사고를 원천적으로 막을 수 있습니다. 암복호화는 이 핸들로 수행하되 키 바이트 자체는 자바스크립트 코드조차 볼 수 없습니다.

이 선택은 제로널리지 제품에서 특히 중요합니다. 키가 절대 서버로 나가지 않는다는 약속은 코드가 그렇게 짜여 있다는 신뢰만으로는 부족하고 플랫폼 차원에서 키를 꺼낼 수 없게 만들어야 실수의 여지가 줄어듭니다. non-extractable 키는 그 약속을 브라우저가 강제하도록 만드는 장치입니다.

파일 키를 따로 두는 이유

메타데이터 서브키가 직접 메타데이터를 암호화하는 것과 달리, 파일 본문은 마스터키 계열로 직접 암호화하지 않습니다. 대신 파일마다 무작위 32바이트 FileKey를 새로 만들어 그 키로 본문을 암호화하고 FileKey 자체는 파일 래핑 서브키로 AES-KW 감싸서 보관합니다. 이 한 겹을 더 두는 이유는 유연성입니다. 파일 키가 마스터키와 분리되어 있으면, 나중에 패스워드를 바꿔도 모든 파일을 다시 암호화할 필요 없이 래핑만 새로 하면 됩니다.

또한 파일 키를 파일 단위로 독립시키면, 미래에 특정 파일만 공유하거나 특정 파일의 키만 회전하는 기능을 얹을 여지가 생깁니다. 마스터 패스워드에서 파일 본문까지 이어지는 사슬을 마스터키, 래핑 서브키, 파일 키의 세 마디로 끊어 두면 각 마디를 독립적으로 다룰 수 있습니다. 키 계층을 얕게 두지 않고 이렇게 설계한 것은 운영과 확장을 염두에 둔 결정이었습니다.

이 파일 키로 실제 본문을 어떻게 암호화하는지는 XChaCha20 청크 AAD 바인딩에서, 씨앗이 되는 마스터키를 어떻게 파생하는지는 브라우저 Argon2id 키 파생에서 다룹니다. 전체 구조는 제로널리지 암호화 미디어 클라우드 사례에 있습니다.

자주 묻는 질문

왜 마스터키를 직접 암호화 키로 쓰면 안 되나요?

하나의 키를 인증, 메타데이터, 파일 등 여러 용도에 재사용하면 한 용도의 약점이 다른 용도로 번질 수 있고 키 회전이나 부분 무효화가 어려워집니다. HKDF로 용도별 서브키를 도메인 분리해 파생하면 각 용도가 독립된 키를 갖게 되어 한 경로의 문제가 다른 경로로 전파되지 않습니다.

non-extractable 키가 실제로 어떤 위험을 막나요?

키 바이트를 자바스크립트가 읽을 수 없게 만들어 실수로 키를 콘솔에 출력하거나 네트워크로 전송하는 사고를 구조적으로 막습니다. 제로널리지에서 "키는 브라우저를 떠나지 않는다"는 약속은 코드 규율만으로는 깨지기 쉬운데, non-extractable로 만들면 그 규칙을 브라우저 플랫폼이 강제합니다.

파일마다 키를 따로 두면 관리가 복잡하지 않나요?

파일 키는 파일 래핑 서브키로 감싸 서버에 함께 보관하므로 사용자가 따로 관리할 것은 없습니다. 오히려 이 구조 덕분에 패스워드 변경 시 파일 전체를 재암호화하지 않고 래핑만 갱신하면 되고 향후 파일 단위 공유나 키 회전 같은 기능을 얹기도 수월해집니다.

#HKDF#도메인분리#서브키#AES-KW#키관리

업무자동화 구축이 필요하신가요?

무료 상담 신청