비밀을 보내지 않고도 양쪽이 같은 키를 얻게 해, 전방 비밀성의 바탕을 만듭니다.
다른 암호 모듈은 모두 키가 이미 공유돼 있다고 전제합니다. 키 합의는 그 키를 처음에 어떻게 나눠 갖는지를 다룹니다. 양쪽이 각자 개인키를 만들고 공개키만 교환한 뒤, 자기 개인키와 상대 공개키를 결합하면 같은 값이 나옵니다. 그 값은 한 번도 네트워크를 타지 않습니다.
자기 개인키와 상대 공개키를 결합해, 한 번도 전송되지 않은 공통 값을 얻습니다.
세션마다 키쌍을 버리면, 나중에 장기 키가 유출돼도 과거 트래픽은 복호되지 않습니다.
합의 자체는 상대가 누구인지 확인하지 않습니다. 공개키는 서명이나 인증서로 따로 인증해야 합니다.
공격자가 암호화된 트래픽을 지금 저장해 두었다가 나중에 서버 개인키를 손에 넣는 상황을 생각해 봅시다. 키 교환 없이 세션 키를 서버 키로 감싸 보냈다면 저장된 트래픽이 전부 복호됩니다. 세션마다 임시 키쌍으로 합의하고 그 개인키를 버렸다면, 장기 키를 얻어도 과거 세션은 열리지 않습니다. TLS 1.3이 (EC)DHE를 필수로 만든 이유가 이것입니다.
X25519의 출력은 균등한 32바이트 난수가 아니라 곡선 위 점의 좌표입니다. 통계적 편향이 남아 있으므로 HMAC 키나 AEAD 키로 바로 쓰면 안 되고, 반드시 KDF를 한 번 거쳐야 합니다. RFC 7748과 NIST SP 800-56A 모두 이 단계를 요구하며, 이 모듈은 HKDF를 씁니다.
중간자가 양쪽과 각각 합의하면 양쪽 모두 정상으로 보입니다. 키 합의는 도청을 막을 뿐, 상대가 누구인지는 알려 주지 않습니다. 실제 프로토콜에는 공개키에 서명을 붙이거나 인증서로 묶는 단계가 반드시 함께 있어야 합니다. 이 모듈은 의도적으로 그 절반만 맡습니다.
아래 증명은 글로 된 설명이 아닙니다. 버튼을 누르면 이 서버가 지금 직접 계산합니다.
비밀을 보내지 않고도 나눠 가집니다. 공개키만 주고받았는데 양쪽이 같은 32바이트 값을 계산해 냅니다. 이 값은 통신 경로로 한 번도 오가지 않으므로, 도청자는 두 공개키를 모두 봐도 계산할 수 없습니다.
표준 문서에 실린 테스트 벡터를 그대로 넣어 같은 값이 나오는지 확인합니다.
특별히 고른 공개키를 보내면 상대의 개인키와 상관없이 공유 비밀이 전부 0이 됩니다. 그러면 공격자도 그 값을 압니다. 이 결과를 그대로 키로 쓰면 합의가 의미를 잃으므로 계산 단계에서 막습니다.
막아야 할 입력을 실제로 넣고 거부되는지 확인합니다.
규격 원문을 먼저 실었습니다. 사례는 이 분야에서 실제로 보안이 뚫린 일을 다룬 자료입니다.
X25519의 원문입니다. §6.1의 벡터를 증명에서 재현합니다.
(EC)DHE를 필수로 만들어 전방 비밀성을 기본값으로 바꾼 규격입니다.
합의 결과를 그대로 키로 쓰지 않고 KDF를 거치게 하는 이유를 설명합니다.
다음 단계
Ed25519 서명으로 공개키를 인증하는 절차와 묶어 중간자 공격이 들어올 틈을 닫습니다.