x25519 — 곡선 위의 키 합의
내 비밀 스칼라와 상대의 공개점으로 둘만 아는 32 바이트를 만든다(RFC 7748). 그 바이트열을 그대로 키로 쓰지 말고 hmac 의 HKDF 로 갈라 쓰는 것이 표준 관행이다.
이 구현이 약속하지 못하는 것
fsel)으로 짰지만, 이 언어에는 경계 검사와 멈춤이 있어 타이밍을 약속할 수 없다. 감사받지 않았다. 작은 위수(small-order) 점을 거르지 않는다 — 상대가 보낸 공개키가 0 을 만드는 점일 수 있으니, 합의 결과가 모두 0 인지 확인하는 것은 부르는 쪽의 몫이다. 개인키를 만드는 일(엔트로피)은 여기 없다 — random 과 cap random 의 자리다.rem w 는 u64 175 원소 이상 --- 작업 공간을 하나로 받는다
let n u64 be x25519.agree shared mysecret theirpub zbuf w .
guard eq n 32 . else return 1 .왜 작업 공간이 하나인가. scalarmult 는 체 원소 아홉과 곱셈 자리를 따로 받는다 — 안에서 읽기에는 그편이 낫다. 그런데 부르는 쪽에서 열넷을 늘어놓으면 파라미터 상한 16 을 금방 먹는다. 이 라이브러리를 쓴 첫 프로그램이 실제로 E-IR-ARITY 로 거절당했다. 그래서 agree 가 w 하나(175 원소 이상)를 잘라 쓰고, 자리 배치(체 원소 아홉 = w[0..144], 곱셈 자리 = w[144..175])는 소스 한 곳에만 있다.
표현을 고른 이야기. 소수는 p = 2^255 − 19. 흔한 참조 구현(ref10)은 조각을 26·25 비트로 담고 조각이 음수가 될 수 있게 두며 자리올림을 산술 오른쪽 시프트로 한다. 이 언어의 shr 은 논리 시프트라 그 배치를 쓸 수 없다. 그래서 음수가 아예 없는 표현(16 조각 × 16 비트, TweetNaCl 배치)을 골랐다. 뺄셈은 a − b 대신 a + 4p − b 로 한다 — 4p ≡ 0 (mod p) 이므로 값은 같고 모든 중간값이 음이 아니다. 도구의 한계가 표현을 골랐는데, 고른 쪽이 추론하기 더 쉬운 쪽이었다.
| op | 하는 일 | 요구 · 답 |
|---|---|---|
agree | 스칼라 × 점 → 공유 비밀 32 바이트(작업 공간 하나) | w ≥ 175 · 나머지 32 바이트씩. 답 32, 0 이면 실패 |
scalarmult | 같은 계산, 작업 공간을 낱개로 | 인자 열넷 |
fzero · fone · fcopy · fcar | 체 원소 초기화 · 복사 · 자리올림 | 위 배치를 아는 코드용 |
fadd · fsub · fmul · fsq · fmul121665 | 체 덧셈 · 뺄셈 · 곱 · 제곱 · 상수곱 | 〃 |
finv · fsel · funpack · fpack | 역원 · 조건부 교환 · 바이트 ↔ 원소 | 〃 |
표 50.1 — x25519 의 op
체 산술이 export 인 것은 시험하기 위해서다(항등식을 잰다). 새 프로토콜을 짓는 것이 아니라면 agree 만 쓰면 된다. 같은 체를 ed25519 가 재사용한다.
확인하는 것 — RFC 7748 §5.2 스칼라곱 벡터, §6.1 DH 왕복(둘이 만나 같은 비밀을 얻는가), 체 산술의 항등식(a·a⁻¹ = 1 등), VM·네이티브 일치. 짓지 않은 것 — 상수 시간 보장, 작은 위수 점 거르기, 키 생성·클램핑 편의 op, X448.