verify — 인증서 서명과 체인의 한 마디 확인
x509 가 인증서를 읽어 주면, 이 모듈은 그 위에서 인증서 한 장이 다른 한 장에게 서명받았는가를 답한다. 서명 확인에 더해 유효기간 · 이름 이어짐 · 호스트 이름 대조까지, 체인의 한 마디를 잇는 데 필요한 판단을 한 자리에 모았다.
무엇을 약속하고 무엇을 하지 않나
체인은 마디의 줄이다#
웹 서버가 보내는 인증서는 보통 세 층이다. 각 층은 바로 위 층에게 서명받고, 맨 위(뿌리)는 우리가 미리 믿기로 한 것이어야 한다.
뿌리 (신뢰 저장소 안) ← trust.find_anchor 가 찾는다
│ 서명
▼
중간 인증기관 ← link_ok 중간자 · 뿌리
│ 서명
▼
잎 (example.com) ← link_ok 잎 · 중간자 + host_ok 잎 · "example.com"link_ok 를 아래에서 위로 마디마다 부르고, 잎에는 host_ok 를 더한다. 하나라도 1 이 아니면 체인은 끊긴다. 체인을 어떻게 모으는지(서버가 보낸 순서, 몇 마디까지)는 부르는 쪽이 정한다 — 실제 예는 apps/lowget 이다.
| 값 | 뜻 |
|---|---|
1 | 잇는다 — 서명 · CA · 이름 · 기간이 모두 맞다 |
2 | 자식의 발급자 이름이 부모의 주체 이름과 다르다 |
3 | 부모가 남을 발급할 수 있는 인증서(CA)가 아니다 |
4 | 둘 중 하나가 유효기간 밖이다 |
5 | 서명이 맞지 않는다(또는 모르는 알고리즘) |
6 | 서명을 확인할 작업 공간이 모자랐다 — 잰 결과가 아니라 재지 못한 것이다 |
표 50.1 — link_ok 가 내는 수 — 1 이 아니면 거절한 까닭
op#
| op | 하는 일 |
|---|---|
link_ok | 한 마디를 잇는다(위 표). 바이트 작업 공간 1024 · 조각 작업 공간 2200 이상 |
signed_by | 자식이 부모에게 서명받았는가 — ok 1 / ok 0, 자리가 모자라면 error short_workspace |
sig_kind | 자식이 적은 서명 알고리즘: 1 RSA+SHA-256 · 2 ECDSA+SHA-256 · 3 RSA+SHA-384 · 4 ECDSA+SHA-384 · 0 모른다 |
dn_eq | 두 이름이 바이트로 같은가 |
dates_ok | 유효기간이 지금(YYYYMMDDhhmmss 한 수)을 담는가 |
host_ok · san_matches | 호스트 이름이 주체 대체 이름 중 하나와 맞는가 |
ecdsa_rs | DER 로 싼 ECDSA 서명에서 r · s 를 곡선 크기(32 · 48 바이트) 자리에 오른쪽 맞춤으로 꺼낸다 |
curve · curve384 | P-256 · P-384 의 상수(p · n · Gx · Gy)를 작업 공간에 채운다 |
표 50.2 — verify 의 op
설계#
서명은 원본 바이트 위에서 확인한다. x509.tbs_off … tbs_end 를 그대로 해시한다. 베낀 자리에서 확인하면 베끼기가 틀려도 서명이 맞아 보일 수 있다.
곡선은 공개키 길이가 가른다. 65 바이트면 P-256(p256), 97 바이트면 P-384(p384). RSA 는 rsa 로 간다.
이름은 바이트로 견준다. DER 은 한 이름에 한 바이트열이므로 그것이 옳다. 문자열로 풀어 견주면 대소문자 · 인코딩 · 공백 규칙이 끼어들고, 그 규칙마다 «같다» 의 뜻이 조금씩 달라진다.
와일드카드는 맨 앞 한 마디만. *.a.b 는 x.a.b 와 맞고 a.b 나 y.x.a.b 와는 맞지 않는다(RFC 6125 §6.4.3). 대소문자는 아스키로만 내린다.
ecdsa_rs 의 오른쪽 맞춤. DER 정수는 앞에 0 이 붙거나(최상위 비트가 1 이면) 짧을 수 있다. 그냥 베끼면 한 바이트 밀린 값으로 검증하게 되고, 그 실수는 언제나 «서명이 틀렸다» 로만 보인다.
모자람은 실패다. 작업 공간이 좁으면 error short_workspace 다 — 예전에는 «자리가 모자람» 과 «서명이 아님» 이 둘 다 0 이어서, 작업 공간을 잘못 준 프로그램이 «서명이 틀렸다» 로 보였다.