From 3869c802cae2d330fb3f0605c555a3f5fb71ed1d Mon Sep 17 00:00:00 2001 From: Muneeb Sheikh Date: Sun, 11 Oct 2026 13:18:52 -0400 Subject: [PATCH] Validate Base32 quantum lengths and padding --- src/validators/encoding.py | 10 +++++++++- tests/test_encoding.py | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/validators/encoding.py b/src/validators/encoding.py index c4ec2cea..fb341b60 100644 --- a/src/validators/encoding.py +++ b/src/validators/encoding.py @@ -46,7 +46,15 @@ def base32(value: str, /): (Literal[True]): If `value` is a valid base32 encoding. (ValidationError): If `value` is an invalid base32 encoding. """ - return re.fullmatch(r"^[A-Z2-7]+=*$", value) if value else False + return ( + re.fullmatch( + r"(?:[A-Z2-7]{8})*(?:[A-Z2-7]{2}(?:={6})?|[A-Z2-7]{4}(?:={4})?|" + r"[A-Z2-7]{5}(?:={3})?|[A-Z2-7]{7}=?)?", + value, + ) + if value + else False + ) @validator diff --git a/tests/test_encoding.py b/tests/test_encoding.py index 9728a8fe..01a6a2fc 100644 --- a/tests/test_encoding.py +++ b/tests/test_encoding.py @@ -130,3 +130,16 @@ def test_encoding_rejects_trailing_characters( ): """Reject characters outside the encoded value.""" assert isinstance(validate(value + suffix), ValidationError) + + +@pytest.mark.parametrize("value", ["A", "AAA", "AAAAAA", "AB=", "AB===", "AB=======", "ABCDEFGH="]) +def test_base32_rejects_invalid_length_and_padding(value: str): + """Reject symbol counts and padding that cannot encode whole bytes.""" + assert isinstance(base32(value), ValidationError) + + +@pytest.mark.parametrize("value", ["MY======", "MZXQ====", "MZXW6===", "MZXW6YQ=", "MZXW6YTB"]) +def test_base32_accepts_valid_final_quanta(value: str): + """Accept each legal final quantum with or without padding.""" + assert base32(value) is True + assert base32(value.rstrip("=")) is True