ecdsa — ECDSA P-256 서명 생성
개인키와 메시지 해시를 받아 서명 (r, s) 를 낸다(RFC 6979). 검증은 p256 의 ecdsa_verify 다. TLS 서버가 CertificateVerify 를 자기 개인키로 서명할 때 쓴다 — 서명 없이는 서버가 없다.
무엇을 약속하고 무엇을 하지 않나
r = 0 또는 s = 0 이면 다시 하지 않고 실패로 답한다(확률 2−128 쯤) — 그 갈래를 지으면 시험할 수 없는 코드가 생기고, 시험 안 된 암호 코드는 없느니만 못하다.왜 논스를 난수가 아니라 유도하는가. ECDSA 에서 논스는 한 번 새거나 한 번 되풀이되면 개인키가 통째로 드러난다.
s = k⁻¹ (h + r·d) ⇒ d = (s·k − h) / rk 를 알면 그 한 줄로 끝이고, 같은 k 를 두 번 쓰면 두 서명에서 k 가 풀린다. 그리고 난수원이 실패하는 경로는 조용하다 — 빈 엔트로피, 포크 뒤의 같은 상태, 가상 머신 스냅숏 복원. 그래서 난수원을 아예 쓰지 않는다. k = HMAC-DRBG(개인키, 메시지 해시) 다. 같은 (키, 메시지)면 같은 서명이 나오고, 그것은 결함이 아니라 성질이다.
| op | 하는 일 | 요구 |
|---|---|---|
nonce6979 | RFC 6979 §3.2 — (d, h) → k | w ≥ 480 바이트 · wu ≥ 16 조각 |
sign | (d, h) → r ‖ s 64 바이트 | wb ≥ 512 바이트 · wu ≥ 908 조각 |
표 50.1 — ecdsa 의 op
곡선 상수(p · n · Gx · Gy)는 호출자가 준다 — 이 모듈은 표를 들고 있지 않다. 서명은 p256 의 smul_ct 만 쓰고, 그것을 시험이 확인한다. k⁻¹ 은 페르마 거듭제곱인데 지수(n − 2)가 공개라 연산 순서가 고정이다.
넉넉함은 공짜가 아니다. 작업 공간을 처음엔 1052 조각으로 잡았는데 그러면 --run 의 배열 인자 상한(u64 1024)을 넘어 VM 에서 시험할 수 없었다. 빈 자리를 두 번 당겨 908 로 줄였다 — 시험할 수 없는 크기는 크기가 아니라 결함이다. 성능 — sign 은 파라미터 · 지역 · 명령이 많아 타입이 붙은 빠른 경로에 들어가지 않는다. 연결당 서명 한 번이라 지금은 견딜 만하다.
확인하는 것 — RFC 6979 §A.2.5 공식 벡터(논스 k, 메시지 "sample" · "test" 의 r · s 를 바이트로), 낸 서명을 우리 검증기가 받는지, 한 비트를 뒤집으면 거절하는지. 벡터 대조는 “규격대로인가”, 왕복은 “우리 두 쪽이 서로 맞는가” 를 묻는다.