[암호] 블록 암호의 패딩 이해하기
AES 같은 블록 암호는 고정된 크기의 블록을 처리한다. CBC처럼 평문을 블록 단위로 나누는 운용 모드에서 마지막 데이터가 블록 크기에 미치지 못하면, 정해진 규칙으로 바이트를 채우는 패딩이 필요하다.
PKCS#7 방식
CMS(RFC 5652)에 정의된 방식은 부족한 바이트 수를 각 패딩 바이트의 값으로 기록한다. 블록 크기가 8바이트이고 평문이 5바이트라면 3바이트가 부족하므로 다음처럼 붙인다.
원문: 00 00 00 00 00
패딩: 03 03 03
결과: 00 00 00 00 00 03 03 03
복호화한 마지막 바이트가 03이면 뒤의 세 바이트가 모두 03인지 확인한 뒤 제거한다. 원문 길이가 이미 블록 크기의 배수여도 한 블록 전체를 패딩해야 한다. 예를 들어 블록 크기가 8이면 08을 여덟 번 추가한다. 그래야 원문의 마지막 바이트와 패딩을 모호하지 않게 구분할 수 있다.
PKCS#5와 PKCS#7
두 이름을 혼용하는 구현이 많지만 역사적인 정의 범위는 다르다. PKCS#5 패딩은 8바이트 블록을 대상으로 했고, CMS의 패딩 규칙은 1~255바이트 블록 크기로 일반화되어 있다. AES의 블록 크기는 16바이트이므로 보통 PKCS7Padding이라는 이름이 더 정확하다.
모든 모드가 패딩을 요구하는 것은 아니다
CTR처럼 블록 암호를 스트림처럼 사용하는 모드와 GCM 같은 AEAD 모드는 입력 길이를 블록 배수로 맞추기 위한 PKCS#7 패딩이 필요하지 않다. “AES를 쓰면 항상 패딩한다”가 아니라, 사용하는 운용 모드와 API 규격을 확인해야 한다.
패딩은 보안 기능이 아니다
패딩은 길이를 맞추는 인코딩 규칙이지 무결성을 제공하지 않는다. CBC 복호화 오류를 외부에 다르게 노출하면 padding oracle 공격으로 이어질 수 있다. 새 설계에서는 가능하면 인증 암호인 AES-GCM처럼 기밀성과 무결성을 함께 제공하는 검증된 API를 사용하고, 패딩 검사 코드를 직접 구현하지 않는다.
RSA의 OAEP나 PKCS#1 v1.5에도 “padding”이라는 표현이 나오지만, 이것은 블록 암호의 PKCS#7 패딩과 목적과 구조가 전혀 다른 인코딩 방식이다.
댓글남기기