Skip to content

Commit 4db9c17

Browse files
xiehuanyinandgator
authored andcommitted
Reject trailing characters in hashes and encoded values
1 parent db19ffe commit 4db9c17

4 files changed

Lines changed: 40 additions & 10 deletions

File tree

‎src/validators/encoding.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def base16(value: str, /):
2525
(Literal[True]): If `value` is a valid base16 encoding.
2626
(ValidationError): If `value` is an invalid base16 encoding.
2727
"""
28-
return re.match(r"^[0-9A-Fa-f]+$", value) if value else False
28+
return re.fullmatch(r"^[0-9A-Fa-f]+$", value) if value else False
2929

3030

3131
@validator
@@ -46,7 +46,7 @@ def base32(value: str, /):
4646
(Literal[True]): If `value` is a valid base32 encoding.
4747
(ValidationError): If `value` is an invalid base32 encoding.
4848
"""
49-
return re.match(r"^[A-Z2-7]+=*$", value) if value else False
49+
return re.fullmatch(r"^[A-Z2-7]+=*$", value) if value else False
5050

5151

5252
@validator
@@ -67,7 +67,7 @@ def base58(value: str, /):
6767
(Literal[True]): If `value` is a valid base58 encoding.
6868
(ValidationError): If `value` is an invalid base58 encoding.
6969
"""
70-
return re.match(r"^[1-9A-HJ-NP-Za-km-z]+$", value) if value else False
70+
return re.fullmatch(r"^[1-9A-HJ-NP-Za-km-z]+$", value) if value else False
7171

7272

7373
@validator
@@ -89,7 +89,7 @@ def base64(value: str, /):
8989
(ValidationError): If `value` is an invalid base64 encoding.
9090
"""
9191
return (
92-
re.match(r"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", value)
92+
re.fullmatch(r"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", value)
9393
if value
9494
else False
9595
)

‎src/validators/hashes.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def md5(value: str, /):
2525
(Literal[True]): If `value` is a valid MD5 hash.
2626
(ValidationError): If `value` is an invalid MD5 hash.
2727
"""
28-
return re.match(r"^[0-9a-f]{32}$", value, re.IGNORECASE) if value else False
28+
return re.fullmatch(r"^[0-9a-f]{32}$", value, re.IGNORECASE) if value else False
2929

3030

3131
@validator
@@ -46,7 +46,7 @@ def sha1(value: str, /):
4646
(Literal[True]): If `value` is a valid SHA1 hash.
4747
(ValidationError): If `value` is an invalid SHA1 hash.
4848
"""
49-
return re.match(r"^[0-9a-f]{40}$", value, re.IGNORECASE) if value else False
49+
return re.fullmatch(r"^[0-9a-f]{40}$", value, re.IGNORECASE) if value else False
5050

5151

5252
@validator
@@ -67,7 +67,7 @@ def sha224(value: str, /):
6767
(Literal[True]): If `value` is a valid SHA224 hash.
6868
(ValidationError): If `value` is an invalid SHA224 hash.
6969
"""
70-
return re.match(r"^[0-9a-f]{56}$", value, re.IGNORECASE) if value else False
70+
return re.fullmatch(r"^[0-9a-f]{56}$", value, re.IGNORECASE) if value else False
7171

7272

7373
@validator
@@ -91,7 +91,7 @@ def sha256(value: str, /):
9191
(Literal[True]): If `value` is a valid SHA256 hash.
9292
(ValidationError): If `value` is an invalid SHA256 hash.
9393
"""
94-
return re.match(r"^[0-9a-f]{64}$", value, re.IGNORECASE) if value else False
94+
return re.fullmatch(r"^[0-9a-f]{64}$", value, re.IGNORECASE) if value else False
9595

9696

9797
@validator
@@ -115,7 +115,7 @@ def sha384(value: str, /):
115115
(Literal[True]): If `value` is a valid SHA384 hash.
116116
(ValidationError): If `value` is an invalid SHA384 hash.
117117
"""
118-
return re.match(r"^[0-9a-f]{96}$", value, re.IGNORECASE) if value else False
118+
return re.fullmatch(r"^[0-9a-f]{96}$", value, re.IGNORECASE) if value else False
119119

120120

121121
@validator
@@ -140,4 +140,4 @@ def sha512(value: str, /):
140140
(Literal[True]): If `value` is a valid SHA512 hash.
141141
(ValidationError): If `value` is an invalid SHA512 hash.
142142
"""
143-
return re.match(r"^[0-9a-f]{128}$", value, re.IGNORECASE) if value else False
143+
return re.fullmatch(r"^[0-9a-f]{128}$", value, re.IGNORECASE) if value else False

‎tests/test_encoding.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""Test Encodings."""
22

3+
# standard
4+
from typing import Callable
5+
36
# external
47
import pytest
58

@@ -115,3 +118,15 @@ def test_returns_true_on_valid_base64(value: str):
115118
def test_returns_failed_validation_on_invalid_base64(value: str):
116119
"""Test returns failed validation on invalid base64."""
117120
assert isinstance(base64(value), ValidationError)
121+
122+
123+
@pytest.mark.parametrize(
124+
"validate, value",
125+
[(base16, "a3f4b2"), (base32, "MFZWIZLTOQ======"), (base58, "18KToMF5"), (base64, "SGVsbG8=")],
126+
)
127+
@pytest.mark.parametrize("suffix", ["\n", "\r\n", " ", "\nextra"])
128+
def test_encoding_rejects_trailing_characters(
129+
validate: Callable[[str], object], value: str, suffix: str
130+
):
131+
"""Reject characters outside the encoded value."""
132+
assert isinstance(validate(value + suffix), ValidationError)

‎tests/test_hashes.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""Test Hashes."""
22

3+
# standard
4+
from typing import Callable
5+
36
# external
47
import pytest
58

@@ -229,3 +232,15 @@ def test_returns_true_on_valid_sha512(value: str):
229232
def test_returns_failed_validation_on_invalid_sha512(value: str):
230233
"""Test returns failed validation on invalid sha512."""
231234
assert isinstance(sha512(value), ValidationError)
235+
236+
237+
@pytest.mark.parametrize(
238+
"validate, size",
239+
[(md5, 32), (sha1, 40), (sha224, 56), (sha256, 64), (sha384, 96), (sha512, 128)],
240+
)
241+
@pytest.mark.parametrize("suffix", ["\n", "\r\n", " ", "\nextra"])
242+
def test_hash_rejects_trailing_characters(
243+
validate: Callable[[str], object], size: int, suffix: str
244+
):
245+
"""Reject characters outside the fixed-length digest."""
246+
assert isinstance(validate("a" * size + suffix), ValidationError)

0 commit comments

Comments
 (0)