Watch at Ease세상을 읽고, 일상의 답을 찾다.

기술 · 실용 가이드

Python Base64의 validate=True도 다른 표기를 허용한다면? 패딩 비트와 버전 확인

엄격한 디코딩과 하나의 정규 표기는 별도 검사다. 17개 로컬 대조로 패딩 비트, 버전별 인자, 크기 제한, 디코딩한 바이트의 의미를 구분한다.

실측한 두 Base64 표기 쌍과 이진 패딩 비트를 보여 주는 원본 기술 일러스트.
원본 기술 일러스트: CPython3.12.14 엄격 디코딩은 두 쌍을 허용했고 재인코딩은 Zg==와 Zm8=만 반환했다. 다른 버전의 실측이 아니다. Watch at Ease

본 매체의 CPython3.12.14에서 base64.b64decode(value,validate=True)는 Zg==와 Zh==를 모두 바이트 f로, Zm8=와 Zm9=를 모두 fo로 디코딩했다. 엄격한 디코딩 성공만으로 입력 문자열이 정규 표기임을 증명하지는 못한다.

먼저 실제로 필요한 프로토콜을 정한다. 이 글이 시험한 것은 비어 있지 않은 bytes 입력, 표준 Base64 알파벳, 필요한 패딩, 길이 제한, 재인코딩의 완전 일치라는 좁은 정책이다. JWT·서명·MIME 메시지를 검증하지 않는다.

1. 패딩 문자와 사용하지 않는 비트를 구분

실측한 Zg==와 Zh==는 등호 개수가 같고, 마지막 알파벳 문자의 사용하지 않는 비트가 다르다. 엄격한 디코딩은 둘 다 허용했지만 반환 바이트를 재인코딩하면 Zg==만 나와 두 번째 표기가 일치 검사에 실패했다. Zm8=와 Zm9=도 같은 결과였다.

RFC4648은 규격에 맞는 인코더가 사용하지 않는 패딩 비트를 0으로 설정하도록 요구한다. 디코더는 0이 아닌 패딩 비트를 거부할 수 있고, 이를 참조하는 프로토콜은 더 엄격한 요건을 정할 수 있다. 수락됐다는 사실만으로 앱의 단일 표기 규칙에 맞는다고 볼 수 없다.

2. 새 키워드를 쓰기 전에 실행 버전 확인

Python3.15 문서는 0이 아닌 패딩 비트를 거부하는 canonical=True를 추가했다. 알파벳 검사는 validate=True로 명시하고 프로토콜의 패딩·크기 규칙도 유지한다. 본 매체는 문서를 읽었지만 Python3.15를 실행하지 않았다.

실제 CPython3.12.14에 canonical=True를 넘기면 알 수 없는 키워드 인자로 TypeError가 발생했다. 이 환경에서는 validate=True로 디코딩하고 본 표준 패딩 정책에 따라 base64.b64encode(decoded)==encoded를 요구한다. 이는 표기 검사이며 MAC이나 서명을 검증하지 않는다.

3. 제한을 포함한 정책을 끝까지 적용

보조 함수는 입력 형식이 정확히 bytes인지 확인하고 4096바이트 초과 인코딩 입력을 거부한다. 엄격하게 디코딩한 뒤 3072바이트 초과 출력을 거부하고, 앱의 비어 있지 않아야 한다는 규칙과 표준 재인코딩의 일치를 검사한다. 모두 통과한 뒤 바이트를 반환한다.

17개 대조에는 f·fo·foo의 유효 인코딩, 두 패딩 비트 변형, 불필요하거나 과도한 패딩, 줄바꿈, 필수 패딩 누락, URL 안전 문자, 패딩 뒤 추가 데이터와 빈 입력이 포함됐다. 추가 대조는 디코딩 전후 길이 제한, 미지원 키워드, 별도 UTF-8 실패를 검증했다.

4. 형식 통과와 내용의 의미도 별도 검사

완전한 3바이트 foo의 정규 표기는 등호 없는 Zm9v다. 필요한 패딩을 요구한다고 모든 입력에 =를 붙이는 것은 아니다. 실측한 엄격 디코더는 Zm9v=를 거부했다. 빈 Base64는 디코딩됐지만 이 앱은 의도적으로 빈 페이로드를 거부했다.

정규 입력 /w==는 바이트 0xff로 변환돼 표기 정책을 통과했지만 UTF-8 디코딩은 실패했다. 형식이 유효하다고 텍스트·파일의 유효성이나 진위를 증명하지는 않는다. 진단을 위해 실패한 원본 입력을 보존하고, 정확한 형식을 요구하는 계약에서는 문자 삭제나 패딩 추가를 조용히 수행하지 않는다.

입력 길이·엄격 디코딩·페이로드 정책·재인코딩 일치의 네 단계를 보여 주는 원본 일러스트.
원본 기술 일러스트: bytes, 입력 4096·출력 3072바이트 상한과 빈 값 거부는 본 예제 정책이다. Python3.15 인자는 문서로만 확인했다. Watch at Ease