gcm — AES-128-GCM 인증 암호
“아무도 못 읽는다” 와 “아무도 못 고친다” 를 한 번에 준다(NIST SP 800-38D). aes 는 앞의 것만 준다.
무엇을 약속하고 무엇을 하지 않나
decrypt 의 태그 검사 실패는 값이다 — 반환값을 반드시 본다.AAD 는 무엇인가. 숨기지는 않지만 고쳐지면 안 되는 바이트다. TLS 1.3 에서는 레코드의 5 바이트 머리가 그것이다 — 길이는 관찰자가 어차피 보지만, 상대가 그것을 바꾸면 태그가 맞지 않아야 한다. aead 의 seal·unseal 과 달리 이 모듈은 encrypt·decrypt 라는 이름을 쓴다. 두 모듈이 같은 이름을 가지면 한정해 불러도 처리기가 다른 쪽 시그니처로 인자 수를 재는 결함이 있어 이름을 갈라 피했다.
| op | 하는 일 | 요구 |
|---|---|---|
gmul128 | GHASH 의 GF(2128) 곱 — z ← z·h | z ≥ 16 · h ≥ 16 · v ≥ 16 |
encrypt | msg → 암호문과 16 바이트 태그 | nonce = 12 · key = 16 |
decrypt | 태그를 먼저 확인하고 평문을 낸다 | 실패하면 0 을 답하고 평문을 주지 않는다 |
표 50.1 — gcm 의 op
뒷받침(scratch)은 호출자가 든다. 모자라면 0 을 답하고 아무것도 쓰지 않는다 — 가드가 지킨다.
GHASH 의 비트 차례 — 사람이 미끄러지는 자리. GF(2128) 의 축약 다항식은 x^128 + x^7 + x^2 + x + 1 인데, GCM 은 비트 차례를 뒤집어 쓴다 — 블록의 첫 바이트 최상위 비트가 x0 이다. 그래서 곱셈이 오른쪽 시프트로 돌고, 넘친 비트는 앞 바이트에 0xE1 로 되돌아온다. 이 관례를 반대로 읽으면 암호문은 맞는데 태그만 통째로 달라져 “복호가 안 된다” 로만 보인다.
논스에 대해 다시. GCM 은 카운터 모드라 같은 (키, 논스)가 같은 키스트림을 낸다. 두 평문의 XOR 이 드러나고, 더 나쁘게는 GHASH 인증키를 풀 수 있는 방정식이 생겨 상대가 임의의 메시지를 위조할 수 있다. TLS 1.3 은 논스를 시퀀스 번호에서 유도해 이것을 피한다(tls13 의 record_nonce). 직접 쓴다면 그 방식을 따른다 — 난수 논스는 96 비트에서 충돌이 생각보다 이르다.
확인하는 것 — NIST GCM 시험 벡터, RFC 8448 §3 의 레코드 암호문(암호문과 태그까지 바이트 그대로), VM·네이티브 일치.