10
10
from enum import Enum
11
11
from typing import TYPE_CHECKING , Annotated , Any , Literal , NewType , Optional , Union , get_args
12
12
13
+ import packaging
14
+ import packaging .tags
15
+ import packaging .utils
16
+ import packaging .version
13
17
import sigstore .errors
14
18
from annotated_types import MinLen # noqa: TCH002
15
19
from cryptography import x509
@@ -291,14 +295,17 @@ def verify(
291
295
# be an exact match for their distribution filename.
292
296
# See: https://github.com/pypi/warehouse/issues/18128
293
297
# See: https://github.com/trailofbits/pypi-attestations/issues/123
294
- _check_dist_filename (subject .name )
295
- subject_name = subject .name
298
+ parsed_subject_name = _check_dist_filename (subject .name )
296
299
except ValueError as e :
297
300
raise VerificationError (f"invalid subject: { str (e )} " )
298
301
299
- if subject_name != dist .name :
302
+ # NOTE: Cannot fail, since we validate the `Distribution` name
303
+ # on construction.
304
+ parsed_dist_name = _check_dist_filename (dist .name )
305
+
306
+ if parsed_subject_name != parsed_dist_name :
300
307
raise VerificationError (
301
- f"subject does not match distribution name: { subject_name } != { dist .name } "
308
+ f"subject does not match distribution name: { subject . name } != { dist .name } "
302
309
)
303
310
304
311
digest = subject .digest .root .get ("sha256" )
@@ -392,7 +399,17 @@ def _der_decode_utf8string(der: bytes) -> str:
392
399
return der_decode (der , UTF8String )[0 ].decode () # type: ignore[no-any-return]
393
400
394
401
395
- def _check_dist_filename (dist : str ) -> None :
402
+ _SdistName = tuple [packaging .utils .NormalizedName , packaging .version .Version ]
403
+ _BdistName = tuple [
404
+ packaging .utils .NormalizedName ,
405
+ packaging .version .Version ,
406
+ packaging .utils .BuildTag ,
407
+ frozenset [packaging .tags .Tag ],
408
+ ]
409
+ _DistName = Union [_SdistName , _BdistName ]
410
+
411
+
412
+ def _check_dist_filename (dist : str ) -> _DistName :
396
413
"""Validate a distribution filename for well-formedness.
397
414
398
415
This does **not** fully normalize the filename. For example,
@@ -406,10 +423,10 @@ def _check_dist_filename(dist: str) -> None:
406
423
# already rejects non-lowercase variants.
407
424
if dist .endswith (".whl" ):
408
425
# `parse_wheel_filename` raises a supertype of ValueError on failure.
409
- parse_wheel_filename (dist )
426
+ return parse_wheel_filename (dist )
410
427
elif dist .endswith ((".tar.gz" , ".zip" )):
411
428
# `parse_sdist_filename` raises a supertype of ValueError on failure.
412
- parse_sdist_filename (dist )
429
+ return parse_sdist_filename (dist )
413
430
else :
414
431
raise ValueError (f"unknown distribution format: { dist } " )
415
432
0 commit comments