Lowent 매뉴얼←↑→

aes — AES-128 블록 암호

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

16 바이트를 키로 뒤섞어 16 바이트를 낸다(FIPS 197). 그게 전부다 — 길이가 변하지 않고, 인증도 없고, 같은 입력은 언제나 같은 출력을 낸다. TLS 1.3 이 TLS_AES_128_GCM_SHA256 을 MUST 로 요구하므로(RFC 8446 §9.1) 있다.

혼자 쓰는 모듈이 아니다

같은 평문 블록이 같은 암호문 블록이 되므로 패턴이 그대로 보이고, 상대가 암호문을 고쳐도 알 수 없다. 실제로 필요한 것은 gcm 의 encrypt · decrypt 이고, 이 모듈은 그 밑의 부품이다. 상수 시간을 약속하지 않고 감사받지 않았다. AES-NI 를 쓰지 않는 순수 Lowent 구현이라 느리다 — 처리량이 필요하면 aead (ChaCha20-Poly1305)를 먼저 고려한다. 키 길이는 128 비트뿐이다.
op하는 일요구
gmulGF(28) 곱(기약다항식 0x11b)—
ginvGF(28) 역원 — x^254(페르마)0 의 역원은 0
sbox · inv_sboxS-box 한 바이트 — 표가 아니라 정의로 계산 · 역 S-box—
expand_key16 바이트 키 → 라운드 키 176 바이트rk ≥ 176 · key ≥ 16
encrypt_blockst 16 바이트를 제자리에서 암호화rk ≥ 176 · st ≥ 16 · tmp ≥ 16

표 50.1 — aes 의 op

복호 블록은 없다. GCM 은 카운터 모드라 암호화만 쓴다 — 복호도 암호화로 한다. inv_sbox 가 있는 것은 언젠가 지을 자리를 비워 둔 것이지 지었다는 뜻이 아니다.

S-box 를 표로 적지 않는다. 256 개 상수를 손으로 옮겨 적는 대신 정의 S(x) = 아핀변환(x⁻¹ in GF(2^8)) 을 그대로 쓴다. 옮겨 적을 표가 없으면 옮겨 적다 틀릴 일도 없다. 시험이 계산한 256 개를 정본 표와 대조한다.

성능 — 재 보니 이랬다. 개발 저장소의 측정에서 sbox 한 번이 180 ns(표를 읽는다면 7.5 ns), encrypt_block 한 블록이 약 31 µs 이고 그중 93 % 가 sbox 160 회였다. AES-128-GCM 전체는 0.46 MB/s, ChaCha20-Poly1305 는 41.8 MB/s. 그중 15 배는 이미 갚았다 — ginv 가 x^254 를 254 번 곱하던 것을 제곱-곱으로 바꿔 곱셈이 254 → 15 가 됐고 시험 벡터는 한 자리도 움직이지 않았다. 표를 쓰면 GCM 이 2.5 MB/s 쯤 되겠지만 여전히 ChaCha20 보다 17 배 느리고, 표는 비밀 색인 캐시 부채널 을 들여온다 — AES 의 고전적인 공격 자리다. 느린 대비책을 위해 부채널을 사지 않는다.

확인하는 것 — FIPS 197 부록 B · C 시험 벡터, RFC 8448 §3 의 레코드 암호문(끝까지 써 본다), VM·네이티브 일치.