Lowent 매뉴얼←↑→

gcm — AES-128-GCM 인증 암호

소스
lib/gcm.low
층
L0 — 순수 계산(호출자의 뒷받침)
권한
없음

“아무도 못 읽는다” 와 “아무도 못 고친다” 를 한 번에 준다(NIST SP 800-38D). aes 는 앞의 것만 준다.

무엇을 약속하고 무엇을 하지 않나

상수 시간을 약속하지 않고 감사받지 않았다. 논스를 절대 되풀이하지 않는다 — 같은 키로 같은 논스를 두 번 쓰면 GCM 은 평문과 인증키를 함께 잃는다. 이 모드에서 가장 비싼 실수다. 느리다 — 개발 저장소의 측정에서 초당 0.46 MB 로, 같은 기계의 ChaCha20-Poly1305(41.8 MB)보다 훨씬 느렸다. 그래서 스위트 선호는 ChaCha20 이다. 이 모듈은 규격이 MUST 라 정확하게 있는 것이지 빠르라고 있는 것이 아니다. decrypt 의 태그 검사 실패는 값이다 — 반환값을 반드시 본다.

AAD 는 무엇인가. 숨기지는 않지만 고쳐지면 안 되는 바이트다. TLS 1.3 에서는 레코드의 5 바이트 머리가 그것이다 — 길이는 관찰자가 어차피 보지만, 상대가 그것을 바꾸면 태그가 맞지 않아야 한다. aead 의 seal·unseal 과 달리 이 모듈은 encrypt·decrypt 라는 이름을 쓴다. 두 모듈이 같은 이름을 가지면 한정해 불러도 처리기가 다른 쪽 시그니처로 인자 수를 재는 결함이 있어 이름을 갈라 피했다.

op하는 일요구
gmul128GHASH 의 GF(2128) 곱 — z ← z·hz ≥ 16 · h ≥ 16 · v ≥ 16
encryptmsg → 암호문과 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·네이티브 일치.