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