diff --git a/src/pypi_attestation_models/_impl.py b/src/pypi_attestation_models/_impl.py index b0b5316..690ef64 100644 --- a/src/pypi_attestation_models/_impl.py +++ b/src/pypi_attestation_models/_impl.py @@ -7,7 +7,6 @@ import binascii from base64 import b64decode, b64encode -from hashlib import sha256 from typing import TYPE_CHECKING, Annotated, Any, Literal, NewType import rfc8785 @@ -17,6 +16,7 @@ from cryptography.hazmat.primitives import serialization from pydantic import BaseModel from pydantic_core import ValidationError +from sigstore._utils import _sha256_streaming from sigstore.models import Bundle, LogEntry if TYPE_CHECKING: @@ -116,9 +116,14 @@ class AttestationPayload(BaseModel): @classmethod def from_dist(cls, dist: Path) -> AttestationPayload: """Create an `AttestationPayload` from a distribution file.""" + with dist.open(mode="rb", buffering=0) as io: + # Replace this with `hashlib.file_digest()` once + # our minimum supported Python is >=3.11 + digest = _sha256_streaming(io).hex() + return AttestationPayload( distribution=dist.name, - digest=sha256(dist.read_bytes()).hexdigest(), + digest=digest, ) def sign(self, signer: Signer) -> Attestation: diff --git a/test/test_impl.py b/test/test_impl.py index f69d639..5fc34bc 100644 --- a/test/test_impl.py +++ b/test/test_impl.py @@ -160,3 +160,4 @@ def test_attestation_payload(self) -> None: expected = f'{{"digest":"{payload.digest}","distribution":"{payload.distribution}"}}' assert bytes(payload) == bytes(expected, "utf-8") + assert json.loads(bytes(payload)) == json.loads(expected)