From 87824370c59ee32ccbda334ba2ace43a52242396 Mon Sep 17 00:00:00 2001 From: Facundo Tuesca Date: Tue, 30 Apr 2024 18:45:04 +0200 Subject: [PATCH] Use sigstore-python for the data models --- pyproject.toml | 3 +- src/pypi_attestation_models/__init__.py | 2 - src/pypi_attestation_models/_impl.py | 127 ++++-------------- .../rfc8785-0.0.2-py3-none-any.whl.json | 48 ------- .../rfc8785-0.0.2-py3-none-any.whl.sigstore | 60 --------- test/assets/rfc8785-0.1.2-py3-none-any.whl | Bin 0 -> 9172 bytes .../rfc8785-0.1.2-py3-none-any.whl.json | 49 +++++++ .../rfc8785-0.1.2-py3-none-any.whl.sigstore | 57 ++++++++ test/test_impl.py | 87 +++++++----- 9 files changed, 187 insertions(+), 246 deletions(-) delete mode 100644 test/assets/rfc8785-0.0.2-py3-none-any.whl.json delete mode 100644 test/assets/rfc8785-0.0.2-py3-none-any.whl.sigstore create mode 100644 test/assets/rfc8785-0.1.2-py3-none-any.whl create mode 100644 test/assets/rfc8785-0.1.2-py3-none-any.whl.json create mode 100644 test/assets/rfc8785-0.1.2-py3-none-any.whl.sigstore diff --git a/pyproject.toml b/pyproject.toml index 3c4b62e..daffcc2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,8 @@ classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: Apache Software License", ] -dependencies = ["sigstore-protobuf-specs"] +# TODO pin sigstore since we deppend on Bundle._inner, which is an object from the protobuf models and could change +dependencies = ["cryptography", "pydantic", "sigstore @ git+ssh://git@github.com/sigstore/sigstore-python@7583a787ab808d3780e1fcdae86b8420fde939b8"] requires-python = ">=3.9" [project.optional-dependencies] diff --git a/src/pypi_attestation_models/__init__.py b/src/pypi_attestation_models/__init__.py index f1816b2..b3ba743 100644 --- a/src/pypi_attestation_models/__init__.py +++ b/src/pypi_attestation_models/__init__.py @@ -6,7 +6,6 @@ Attestation, ConversionError, InvalidAttestationError, - InvalidBundleError, VerificationMaterial, pypi_to_sigstore, sigstore_to_pypi, @@ -16,7 +15,6 @@ "Attestation", "ConversionError", "InvalidAttestationError", - "InvalidBundleError", "VerificationMaterial", "pypi_to_sigstore", "sigstore_to_pypi", diff --git a/src/pypi_attestation_models/_impl.py b/src/pypi_attestation_models/_impl.py index d57df42..75f8dd8 100644 --- a/src/pypi_attestation_models/_impl.py +++ b/src/pypi_attestation_models/_impl.py @@ -6,30 +6,20 @@ from __future__ import annotations import binascii -import json from base64 import b64decode, b64encode -from dataclasses import asdict, dataclass -from typing import Any, Literal +from typing import Annotated, Any, Literal, NewType -import sigstore_protobuf_specs.dev.sigstore.bundle.v1 as sigstore -from sigstore_protobuf_specs.dev.sigstore.common.v1 import MessageSignature, X509Certificate -from sigstore_protobuf_specs.dev.sigstore.rekor.v1 import TransparencyLogEntry - -_NO_CERTIFICATES_ERROR_MESSAGE = "No certificates found in Sigstore Bundle" +from annotated_types import MinLen # noqa: TCH002 +from cryptography import x509 +from cryptography.hazmat.primitives import serialization +from pydantic import BaseModel +from sigstore.models import Bundle, LogEntry class ConversionError(ValueError): """The base error for all errors during conversion.""" -class InvalidBundleError(ConversionError): - """The Sigstore Bundle given as input is not valid.""" - - def __init__(self: InvalidBundleError, msg: str) -> None: - """Initialize an `InvalidBundleError`.""" - super().__init__(f"Could not convert input Bundle: {msg}") - - class InvalidAttestationError(ConversionError): """The PyPI Attestation given as input is not valid.""" @@ -38,8 +28,10 @@ def __init__(self: InvalidAttestationError, msg: str) -> None: super().__init__(f"Could not convert input Attestation: {msg}") -@dataclass -class VerificationMaterial: +TransparencyLogEntry = NewType("TransparencyLogEntry", dict[str, Any]) + + +class VerificationMaterial(BaseModel): """Cryptographic materials used to verify attestation objects.""" certificate: str @@ -47,23 +39,14 @@ class VerificationMaterial: The signing certificate, as `base64(DER(cert))`. """ - transparency_entries: list[dict[str, Any]] + transparency_entries: Annotated[list[TransparencyLogEntry], MinLen(1)] """ One or more transparency log entries for this attestation's signature and certificate. """ - @staticmethod - def from_dict(dict_input: dict[str, Any]) -> VerificationMaterial: - """Create a VerificationMaterial object from a dict.""" - return VerificationMaterial( - certificate=dict_input["certificate"], - transparency_entries=dict_input["transparency_entries"], - ) - -@dataclass -class Attestation: +class Attestation(BaseModel): """Attestation object as defined in PEP 740.""" version: Literal[1] @@ -82,71 +65,25 @@ class Attestation: is the raw bytes of the signing operation. """ - def to_json(self: Attestation) -> str: - """Serialize the attestation object into JSON.""" - return json.dumps(asdict(self)) - - @staticmethod - def from_dict(dict_input: dict[str, Any]) -> Attestation: - """Create an Attestation object from a dict.""" - return Attestation( - version=dict_input["version"], - verification_material=VerificationMaterial.from_dict( - dict_input["verification_material"], - ), - message_signature=dict_input["message_signature"], - ) - - -@dataclass -class Provenance: - """Provenance object as defined in PEP 740.""" - - version: Literal[1] - """ - The provenance object's version, which is always 1. - """ - - publisher: object | None - """ - An optional open-ended JSON object, specific to the kind of Trusted - Publisher used to publish the file, if one was used. - """ - attestations: list[Attestation] - """ - One or more attestation objects. - """ - - -def sigstore_to_pypi(sigstore_bundle: sigstore.Bundle) -> Attestation: - """Convert a Sigstore Bundle into a PyPI attestation object, as defined in PEP 740.""" - certificate = sigstore_bundle.verification_material.certificate.raw_bytes - if certificate == b"": - # If there's no single certificate, we check for a leaf certificate in the - # x509_certificate_chain.certificates` field. - certificates = sigstore_bundle.verification_material.x509_certificate_chain.certificates - if not certificates: - raise InvalidBundleError(_NO_CERTIFICATES_ERROR_MESSAGE) - # According to the spec, the first member of the sequence MUST be the leaf certificate - # conveying the signing key - certificate = certificates[0].raw_bytes - - certificate = b64encode(certificate).decode("ascii") - tlog_entries = [t.to_dict() for t in sigstore_bundle.verification_material.tlog_entries] - verification_material = VerificationMaterial( - certificate=certificate, - transparency_entries=tlog_entries, +def sigstore_to_pypi(sigstore_bundle: Bundle) -> Attestation: + """Convert a Sigstore Bundle into a PyPI attestation as defined in PEP 740.""" + certificate = sigstore_bundle.signing_certificate.public_bytes( + encoding=serialization.Encoding.DER ) + signature = sigstore_bundle._inner.message_signature.signature # noqa: SLF001 return Attestation( version=1, - verification_material=verification_material, - message_signature=b64encode(sigstore_bundle.message_signature.signature).decode("ascii"), + verification_material=VerificationMaterial( + certificate=b64encode(certificate).decode("ascii"), + transparency_entries=[sigstore_bundle.log_entry._to_dict_rekor()], # noqa: SLF001 + ), + message_signature=b64encode(signature).decode("ascii"), ) -def pypi_to_sigstore(pypi_attestation: Attestation) -> sigstore.Bundle: +def pypi_to_sigstore(pypi_attestation: Attestation) -> Bundle: """Convert a PyPI attestation object as defined in PEP 740 into a Sigstore Bundle.""" try: certificate_bytes = b64decode(pypi_attestation.verification_material.certificate) @@ -154,18 +91,10 @@ def pypi_to_sigstore(pypi_attestation: Attestation) -> sigstore.Bundle: except binascii.Error as err: raise InvalidAttestationError(str(err)) from err - certificate = X509Certificate(raw_bytes=certificate_bytes) - tlog_entries = [ - TransparencyLogEntry().from_dict(x) - for x in pypi_attestation.verification_material.transparency_entries - ] + tlog_entry = pypi_attestation.verification_material.transparency_entries[0] - verification_material = sigstore.VerificationMaterial( - certificate=certificate, - tlog_entries=tlog_entries, - ) - return sigstore.Bundle( - media_type="application/vnd.dev.sigstore.bundle+json;version=0.3", - verification_material=verification_material, - message_signature=MessageSignature(signature=signature_bytes), + return Bundle.from_parts( + cert=x509.load_der_x509_certificate(certificate_bytes), + sig=signature_bytes, + log_entry=LogEntry._from_dict_rekor(tlog_entry), # noqa: SLF001 ) diff --git a/test/assets/rfc8785-0.0.2-py3-none-any.whl.json b/test/assets/rfc8785-0.0.2-py3-none-any.whl.json deleted file mode 100644 index 2d61d51..0000000 --- a/test/assets/rfc8785-0.0.2-py3-none-any.whl.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "version": 1, - "verification_material": { - "certificate": "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", - "transparency_entries": [ - { - "logIndex": "76153733", - "logId": { - "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" - }, - "kindVersion": { - "kind": "hashedrekord", - "version": "0.0.1" - }, - "integratedTime": "1709764175", - "inclusionPromise": { - "signedEntryTimestamp": "MEUCIBf3PdlV0ZcrEbGAEgk4MqZ/2XrXVaoNgNY7SPtb4UAjAiEAtaNeC7d3W2nVXv3k/bO9kVn8tGm/VLqNmq6HmXip7gk=" - }, - "inclusionProof": { - "logIndex": "71990302", - "rootHash": "H4vwFjFMXB1wMptG/HzWZxTAgVMQeRLyxYVAjj0V77Q=", - "treeSize": "71990304", - "hashes": [ - "XXmMcYxafHY92ufCKlDRFQwaNYJ3DKDjVCuLrI3RgS4=", - "MAl1oWo7cvENduy3CJT4vKGWWm2THPYS857XyrIIGnQ=", - "oL5/l+vGeEBm3EMXuGB6bKzrDQgob9s16l2LqzsmZg0=", - "17Uy+jw+z+pkXH5rjqeDC2vmP9CRuCa6Ci7AZw99HjU=", - "yg2mFeuGCgCZW2AYrQZWlRs8VYsz1xInyl3sFzTOC84=", - "yTX4XLfADd7KZrB1B1BOaHpH122CDK+GzwDXlay8j+k=", - "mV2QNtrV+WDkXBNPjE3Im6+kLyPsZoMfQguW8X1KBKo=", - "hdXMInhF1t95XTq7cglzKp5fw6gL4Z/NKAOpfM8X0hE=", - "kpmAb9wGPYqvRAzw4czyQLynD593JMN/wxSv0qD66JE=", - "AcSXgK1w5baiJJ/RBVtApFQMMIZJtwE1Q6UASzPH+zs=", - "CayiUjRB6Htq5omYI+/lGCgRJmGU1DDkMvBLZiP1r4w=", - "XE7+Pykrktsdsy1ru6V4IsFAOKTJosu3KUa0//TCa0w=", - "7Z18YLBAvejEV4nJHIKoks/xlijnhR005qTW2w4QtHg=", - "98enzMaC+x5oCMvIZQA5z8vu2apDMCFvE/935NfuPw8=" - ], - "checkpoint": { - "envelope": "rekor.sigstore.dev - 2605736670972794746\n71990304\nH4vwFjFMXB1wMptG/HzWZxTAgVMQeRLyxYVAjj0V77Q=\n\n— rekor.sigstore.dev wNI9ajBFAiBXGe9HyQ/f0gV0XkOPNYPiKxN43AbeZdMD0SppBabIowIhAL+jT6Z/wWrGrtn7qdldgVH/jlRAweoFIhTnKvvLNysu\n" - } - }, - "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIwYTE4NjY2NjM0MGI1N2MxYzhmMzY1NDI5YTA3ZjU1MjYxYTFhNjBiMjk1N2Y2M2IyOTQ4MjBjNGUzYzBiNWU0In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJSElLV3pTd3dJNjJHcUhkb3Zjc1dpVzBLYk5hSFMwYjQyTEJzeHlSVk5EckFpRUErdEFLbkcrdk9mbXpGNVNmeEJrRlduaDdvR2xsNWhPRWl6YVdvK1dYdHZnPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVZDZha05EUW14VFowRjNTVUpCWjBsVlQzaFNZbXd6VUVSU2VVWnNWbFZwU0ZwVFZHcElWRFZ3ZGpnNGQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJkMDE2UVRKTmFrbDVUMVJOTVZkb1kwNU5hbEYzVFhwQk1rMXFTWHBQVkUweFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVUzTURsWVdGZHRSazlGZEhKWlMzcHFSRkJxWjIwMVRVdFRZV05QVVdGRVJXbFhkVWtLVVVwSU5IVjROV3h1U1Rndk1XTTFWVlIyVkVOMGRtZzNVR2RNVW05aVFXWmpiamhUWmtGdmJtbHJNa3RCUlhoak1HRlBRMEpZVFhkbloxWjJUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZWZVdaUENtRm1RMUY1UVV0cFYzQlRlVkZuUzFvMGFEUktURGRaZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDFwbldVUldVakJTUVZGSUwwSkdkM2RYYjFwWllVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVEROU2VWbFhiSE5pTWxwcFlWaFNlZ3BNTTBwdFdYcG5NMDlFVlhWalNHdDJURzFrY0dSSGFERlphVGt6WWpOS2NscHRlSFprTTAxMlkyMVdjMXBYUm5wYVV6VTFZbGQ0UVdOdFZtMWplVGt3Q2xsWFpIcE1NMWwzVEdwQmRVMXFRVFZDWjI5eVFtZEZSVUZaVHk5TlFVVkNRa04wYjJSSVVuZGplbTkyVEROU2RtRXlWblZNYlVacVpFZHNkbUp1VFhVS1dqSnNNR0ZJVm1sa1dFNXNZMjFPZG1KdVVteGlibEYxV1RJNWRFMUNWVWREYVhOSFFWRlJRbWMzT0hkQlVVbEZRak5LYkdKSFZtaGpNbFYzVG1kWlN3cExkMWxDUWtGSFJIWjZRVUpCZDFGdlRWUkthMXBxWXpST1ZGWnBUa1JDYWxsWFdUSk5WR3N6VFdwRk1WbHRSbXhaYlZreVRWUk5kMXBFVW1sT2VrcHRDbGxYVVhkTmVrRldRbWR2Y2tKblJVVkJXVTh2VFVGRlJVSkJaSGxhVjNoc1dWaE9iRTFEVVVkRGFYTkhRVkZSUW1jM09IZEJVVlZGUm01U2VWbFhiSE1LWWpKYWFXRllVbnBNTTBwdFdYcG5NMDlFVlhWalNHdDNTR2RaUzB0M1dVSkNRVWRFZG5wQlFrSm5VVkZqYlZadFkzazVNRmxYWkhwTU0xbDNUR3BCZFFwTmFrRTNRbWR2Y2tKblJVVkJXVTh2VFVGRlNVSkRNRTFMTW1nd1pFaENlazlwT0haa1J6bHlXbGMwZFZsWFRqQmhWemwxWTNrMWJtRllVbTlrVjBveENtTXlWbmxaTWpsMVpFZFdkV1JETldwaU1qQjNZVUZaUzB0M1dVSkNRVWRFZG5wQlFrTlJVbUZFUm1odlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5Xb0tZakl3ZG1SSVNtaGhWM2gyV20xS2NHUklUWFpqYlZwcVQwUmpORTVUTlhkbFV6aDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsNVdsZDRiQXBaV0U1c1RHNXNkR0pGUW5sYVYxcDZURE5TYUZvelRYWmtha0YxVFVNMGVVMUVaMGREYVhOSFFWRlJRbWMzT0hkQlVXOUZTMmQzYjAxVVNtdGFhbU0wQ2s1VVZtbE9SRUpxV1ZkWk1rMVVhek5OYWtVeFdXMUdiRmx0V1RKTlZFMTNXa1JTYVU1NlNtMVpWMUYzVFhwQlpFSm5iM0pDWjBWRlFWbFBMMDFCUlV3S1FrRTRUVVJYWkhCa1IyZ3hXV2t4YjJJelRqQmFWMUYzVDFGWlMwdDNXVUpDUVVkRWRucEJRa1JCVVhKRVEyeHZaRWhTZDJONmIzWk1NbVJ3WkVkb01RcFphVFZxWWpJd2RtUklTbWhoVjNoMldtMUtjR1JJVFhaamJWcHFUMFJqTkU1VE5YZGxWRUUwUW1kdmNrSm5SVVZCV1U4dlRVRkZUa0pEYjAxTFJFVjVDbHBIV1ROUFJGVXhXV3BSZDFreVJtMU9ha1UxVG5wSmVFNVhTbWhhVjBwdFRtcEZlazFIVVRCWmFtTjVXbTFHYTAxRVRYZEpRVmxMUzNkWlFrSkJSMFFLZG5wQlFrUm5VVk5FUWtKNVdsZGFla3d6VW1oYU0wMTJaR3BCZFUxRE5IbE5RbXRIUTJselIwRlJVVUpuTnpoM1FWRTRSVU4zZDBwT2VsazBUV3BGZWdwUFZHc3pUVU0wUjBOcGMwZEJVVkZDWnpjNGQwRlNRVVZKUVhkbFlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVEROU2VWbFhiSE5pTWxwcENtRllVbnBOUW1OSFEybHpSMEZSVVVKbk56aDNRVkpGUlVOUmQwaE5hazE0VGtSUmVVMTZRbTlDWjI5eVFtZEZSVUZaVHk5TlFVVlRRa1p2VFZkSGFEQUtaRWhDZWs5cE9IWmFNbXd3WVVoV2FVeHRUblppVXprd1kyMUdjR0pIT1cxWmJXd3dZM2s1ZVZwdFRUUk9lbWN4VEc1Q05VeDVOVzVoV0ZKdlpGZEpkZ3BrTWpsNVlUSmFjMkl6WkhwTU0wcHNZa2RXYUdNeVZYVmxWekZ6VVVoS2JGcHVUWFprUjBadVkzazVNazFETkhkTWFrbDNUMEZaUzB0M1dVSkNRVWRFQ25aNlFVSkZkMUZ4UkVObmVFMXRVbTFPZW1jeFRsZEpNRTFIVG1oYWFsbDRUMVJqZVUxVVZtbFpWMVpwV21wWmVFMTZRbXRPUjBrelRXMWFhRnBFUVhvS1RVSmpSME5wYzBkQlVWRkNaemM0ZDBGU1VVVkRVWGRJWTIxV2MxcFhSbnBhVkVKalFtZHZja0puUlVWQldVOHZUVUZGVmtKRk5FMVVSMmd3WkVoQ2VncFBhVGgyV2pKc01HRklWbWxNYlU1MllsTTVNR050Um5CaVJ6bHRXVzFzTUdONU9YbGFiVTAwVG5wbk1VeHVRalZNTWtacVpFZHNkbUp1VFhaamJsWjFDbU41T0RSTlZHTTFUbXBuZVUxRVRUUk1Na1l3WkVkV2RHTklVbnBNZWtWM1JtZFpTMHQzV1VKQ1FVZEVkbnBCUWtablVVbEVRVnAzWkZkS2MyRlhUWGNLWjFsdlIwTnBjMGRCVVZGQ01XNXJRMEpCU1VWbVFWSTJRVWhuUVdSblJHUlFWRUp4ZUhOalVrMXRUVnBJYUhsYVducGpRMjlyY0dWMVRqUTRjbVlyU0FwcGJrdEJUSGx1ZFdwblFVRkJXVFJXTkhWWVkwRkJRVVZCZDBKSVRVVlZRMGxGYjFONmJEUlNkWHA2TW5jM2RqQXZWbFl4WWprMlJuQmtVRXMwZEhkekNuaDBUM2xtWkhKNVNYSnFhVUZwUlVFd1MwRjROSEkwV0cxaFFXOWpSa0Z0WTNvMUwxQXhOMFk0VDFSaFlucE9UbFJaTVdKV01UbG1lbGRyZDBObldVa0tTMjlhU1hwcU1FVkJkMDFFWVVGQmQxcFJTWGRJWmxVNVlqbElVVk50WTNCVWNqTnhSMVZpVTJWS1pHa3haa3AzUVRad1oyRTFaRTl5YmtGcFFtd3hWZ280ZWt0aFQzUkdlbkpIUTNWaGRsSnJNMXBHYmtGcVJVRXJjMUJsYlZwaVRuRnVObmt2UkhwVU5YQkRaMk5rUmpWc1JWZDJlRTlWUXpOaWN6QjVSMU53Q20weVJWWktSRWxJYkU5elRDdHVZWE15YVRscmRWcDVVUW90TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09In19fX0=" - } - ] - }, - "message_signature": "MEUCIHIKWzSwwI62GqHdovcsWiW0KbNaHS0b42LBsxyRVNDrAiEA+tAKnG+vOfmzF5SfxBkFWnh7oGll5hOEizaWo+WXtvg=" -} \ No newline at end of file diff --git a/test/assets/rfc8785-0.0.2-py3-none-any.whl.sigstore b/test/assets/rfc8785-0.0.2-py3-none-any.whl.sigstore deleted file mode 100644 index 483e943..0000000 --- a/test/assets/rfc8785-0.0.2-py3-none-any.whl.sigstore +++ /dev/null @@ -1,60 +0,0 @@ -{ - "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.2", - "verificationMaterial": { - "x509CertificateChain": { - "certificates": [ - { - "rawBytes": "MIIGzjCCBlSgAwIBAgIUOxRbl3PDRyFlVUiHZSTjHT5pv88wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjQwMzA2MjIyOTM1WhcNMjQwMzA2MjIzOTM1WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE709XXWmFOEtrYKzjDPjgm5MKSacOQaDEiWuIQJH4ux5lnI8/1c5UTvTCtvh7PgLRobAfcn8SfAonik2KAExc0aOCBXMwggVvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUUyfOafCQyAKiWpSyQgKZ4h4JL7YwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wZgYDVR0RAQH/BFwwWoZYaHR0cHM6Ly9naXRodWIuY29tL3RyYWlsb2ZiaXRzL3JmYzg3ODUucHkvLmdpdGh1Yi93b3JrZmxvd3MvcmVsZWFzZS55bWxAcmVmcy90YWdzL3YwLjAuMjA5BgorBgEEAYO/MAEBBCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMBUGCisGAQQBg78wAQIEB3JlbGVhc2UwNgYKKwYBBAGDvzABAwQoMTJkZjc4NTViNDBjYWY2MTk3MjE1YmFlYmY2MTMwZDRiNzJmYWQwMzAVBgorBgEEAYO/MAEEBAdyZWxlYXNlMCQGCisGAQQBg78wAQUEFnRyYWlsb2ZiaXRzL3JmYzg3ODUucHkwHgYKKwYBBAGDvzABBgQQcmVmcy90YWdzL3YwLjAuMjA7BgorBgEEAYO/MAEIBC0MK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20waAYKKwYBBAGDvzABCQRaDFhodHRwczovL2dpdGh1Yi5jb20vdHJhaWxvZmJpdHMvcmZjODc4NS5weS8uZ2l0aHViL3dvcmtmbG93cy9yZWxlYXNlLnltbEByZWZzL3RhZ3MvdjAuMC4yMDgGCisGAQQBg78wAQoEKgwoMTJkZjc4NTViNDBjYWY2MTk3MjE1YmFlYmY2MTMwZDRiNzJmYWQwMzAdBgorBgEEAYO/MAELBA8MDWdpdGh1Yi1ob3N0ZWQwOQYKKwYBBAGDvzABDAQrDClodHRwczovL2dpdGh1Yi5jb20vdHJhaWxvZmJpdHMvcmZjODc4NS5weTA4BgorBgEEAYO/MAENBCoMKDEyZGY3ODU1YjQwY2FmNjE5NzIxNWJhZWJmNjEzMGQ0YjcyZmFkMDMwIAYKKwYBBAGDvzABDgQSDBByZWZzL3RhZ3MvdjAuMC4yMBkGCisGAQQBg78wAQ8ECwwJNzY4MjEzOTk3MC4GCisGAQQBg78wARAEIAweaHR0cHM6Ly9naXRodWIuY29tL3RyYWlsb2ZiaXRzMBcGCisGAQQBg78wAREECQwHMjMxNDQyMzBoBgorBgEEAYO/MAESBFoMWGh0dHBzOi8vZ2l0aHViLmNvbS90cmFpbG9mYml0cy9yZmM4Nzg1LnB5Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvdGFncy92MC4wLjIwOAYKKwYBBAGDvzABEwQqDCgxMmRmNzg1NWI0MGNhZjYxOTcyMTViYWViZjYxMzBkNGI3MmZhZDAzMBcGCisGAQQBg78wARQECQwHcmVsZWFzZTBcBgorBgEEAYO/MAEVBE4MTGh0dHBzOi8vZ2l0aHViLmNvbS90cmFpbG9mYml0cy9yZmM4Nzg1LnB5L2FjdGlvbnMvcnVucy84MTc5NjgyMDM4L2F0dGVtcHRzLzEwFgYKKwYBBAGDvzABFgQIDAZwdWJsaWMwgYoGCisGAQQB1nkCBAIEfAR6AHgAdgDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynujgAAAY4V4uXcAAAEAwBHMEUCIEoSzl4Ruzz2w7v0/VV1b96FpdPK4twsxtOyfdryIrjiAiEA0KAx4r4XmaAocFAmcz5/P17F8OTabzNNTY1bV19fzWkwCgYIKoZIzj0EAwMDaAAwZQIwHfU9b9HQSmcpTr3qGUbSeJdi1fJwA6pga5dOrnAiBl1V8zKaOtFzrGCuavRk3ZFnAjEA+sPemZbNqn6y/DzT5pCgcdF5lEWvxOUC3bs0yGSpm2EVJDIHlOsL+nas2i9kuZyQ" - } - ] - }, - "tlogEntries": [ - { - "logIndex": "76153733", - "logId": { - "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" - }, - "kindVersion": { - "kind": "hashedrekord", - "version": "0.0.1" - }, - "integratedTime": "1709764175", - "inclusionPromise": { - "signedEntryTimestamp": "MEUCIBf3PdlV0ZcrEbGAEgk4MqZ/2XrXVaoNgNY7SPtb4UAjAiEAtaNeC7d3W2nVXv3k/bO9kVn8tGm/VLqNmq6HmXip7gk=" - }, - "inclusionProof": { - "logIndex": "71990302", - "rootHash": "H4vwFjFMXB1wMptG/HzWZxTAgVMQeRLyxYVAjj0V77Q=", - "treeSize": "71990304", - "hashes": [ - "XXmMcYxafHY92ufCKlDRFQwaNYJ3DKDjVCuLrI3RgS4=", - "MAl1oWo7cvENduy3CJT4vKGWWm2THPYS857XyrIIGnQ=", - "oL5/l+vGeEBm3EMXuGB6bKzrDQgob9s16l2LqzsmZg0=", - "17Uy+jw+z+pkXH5rjqeDC2vmP9CRuCa6Ci7AZw99HjU=", - "yg2mFeuGCgCZW2AYrQZWlRs8VYsz1xInyl3sFzTOC84=", - "yTX4XLfADd7KZrB1B1BOaHpH122CDK+GzwDXlay8j+k=", - "mV2QNtrV+WDkXBNPjE3Im6+kLyPsZoMfQguW8X1KBKo=", - "hdXMInhF1t95XTq7cglzKp5fw6gL4Z/NKAOpfM8X0hE=", - "kpmAb9wGPYqvRAzw4czyQLynD593JMN/wxSv0qD66JE=", - "AcSXgK1w5baiJJ/RBVtApFQMMIZJtwE1Q6UASzPH+zs=", - "CayiUjRB6Htq5omYI+/lGCgRJmGU1DDkMvBLZiP1r4w=", - "XE7+Pykrktsdsy1ru6V4IsFAOKTJosu3KUa0//TCa0w=", - "7Z18YLBAvejEV4nJHIKoks/xlijnhR005qTW2w4QtHg=", - "98enzMaC+x5oCMvIZQA5z8vu2apDMCFvE/935NfuPw8=" - ], - "checkpoint": { - "envelope": "rekor.sigstore.dev - 2605736670972794746\n71990304\nH4vwFjFMXB1wMptG/HzWZxTAgVMQeRLyxYVAjj0V77Q=\n\n— rekor.sigstore.dev wNI9ajBFAiBXGe9HyQ/f0gV0XkOPNYPiKxN43AbeZdMD0SppBabIowIhAL+jT6Z/wWrGrtn7qdldgVH/jlRAweoFIhTnKvvLNysu\n" - } - }, - "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIwYTE4NjY2NjM0MGI1N2MxYzhmMzY1NDI5YTA3ZjU1MjYxYTFhNjBiMjk1N2Y2M2IyOTQ4MjBjNGUzYzBiNWU0In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJSElLV3pTd3dJNjJHcUhkb3Zjc1dpVzBLYk5hSFMwYjQyTEJzeHlSVk5EckFpRUErdEFLbkcrdk9mbXpGNVNmeEJrRlduaDdvR2xsNWhPRWl6YVdvK1dYdHZnPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVZDZha05EUW14VFowRjNTVUpCWjBsVlQzaFNZbXd6VUVSU2VVWnNWbFZwU0ZwVFZHcElWRFZ3ZGpnNGQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJkMDE2UVRKTmFrbDVUMVJOTVZkb1kwNU5hbEYzVFhwQk1rMXFTWHBQVkUweFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVUzTURsWVdGZHRSazlGZEhKWlMzcHFSRkJxWjIwMVRVdFRZV05QVVdGRVJXbFhkVWtLVVVwSU5IVjROV3h1U1Rndk1XTTFWVlIyVkVOMGRtZzNVR2RNVW05aVFXWmpiamhUWmtGdmJtbHJNa3RCUlhoak1HRlBRMEpZVFhkbloxWjJUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZWZVdaUENtRm1RMUY1UVV0cFYzQlRlVkZuUzFvMGFEUktURGRaZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDFwbldVUldVakJTUVZGSUwwSkdkM2RYYjFwWllVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVEROU2VWbFhiSE5pTWxwcFlWaFNlZ3BNTTBwdFdYcG5NMDlFVlhWalNHdDJURzFrY0dSSGFERlphVGt6WWpOS2NscHRlSFprTTAxMlkyMVdjMXBYUm5wYVV6VTFZbGQ0UVdOdFZtMWplVGt3Q2xsWFpIcE1NMWwzVEdwQmRVMXFRVFZDWjI5eVFtZEZSVUZaVHk5TlFVVkNRa04wYjJSSVVuZGplbTkyVEROU2RtRXlWblZNYlVacVpFZHNkbUp1VFhVS1dqSnNNR0ZJVm1sa1dFNXNZMjFPZG1KdVVteGlibEYxV1RJNWRFMUNWVWREYVhOSFFWRlJRbWMzT0hkQlVVbEZRak5LYkdKSFZtaGpNbFYzVG1kWlN3cExkMWxDUWtGSFJIWjZRVUpCZDFGdlRWUkthMXBxWXpST1ZGWnBUa1JDYWxsWFdUSk5WR3N6VFdwRk1WbHRSbXhaYlZreVRWUk5kMXBFVW1sT2VrcHRDbGxYVVhkTmVrRldRbWR2Y2tKblJVVkJXVTh2VFVGRlJVSkJaSGxhVjNoc1dWaE9iRTFEVVVkRGFYTkhRVkZSUW1jM09IZEJVVlZGUm01U2VWbFhiSE1LWWpKYWFXRllVbnBNTTBwdFdYcG5NMDlFVlhWalNHdDNTR2RaUzB0M1dVSkNRVWRFZG5wQlFrSm5VVkZqYlZadFkzazVNRmxYWkhwTU0xbDNUR3BCZFFwTmFrRTNRbWR2Y2tKblJVVkJXVTh2VFVGRlNVSkRNRTFMTW1nd1pFaENlazlwT0haa1J6bHlXbGMwZFZsWFRqQmhWemwxWTNrMWJtRllVbTlrVjBveENtTXlWbmxaTWpsMVpFZFdkV1JETldwaU1qQjNZVUZaUzB0M1dVSkNRVWRFZG5wQlFrTlJVbUZFUm1odlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5Xb0tZakl3ZG1SSVNtaGhWM2gyV20xS2NHUklUWFpqYlZwcVQwUmpORTVUTlhkbFV6aDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsNVdsZDRiQXBaV0U1c1RHNXNkR0pGUW5sYVYxcDZURE5TYUZvelRYWmtha0YxVFVNMGVVMUVaMGREYVhOSFFWRlJRbWMzT0hkQlVXOUZTMmQzYjAxVVNtdGFhbU0wQ2s1VVZtbE9SRUpxV1ZkWk1rMVVhek5OYWtVeFdXMUdiRmx0V1RKTlZFMTNXa1JTYVU1NlNtMVpWMUYzVFhwQlpFSm5iM0pDWjBWRlFWbFBMMDFCUlV3S1FrRTRUVVJYWkhCa1IyZ3hXV2t4YjJJelRqQmFWMUYzVDFGWlMwdDNXVUpDUVVkRWRucEJRa1JCVVhKRVEyeHZaRWhTZDJONmIzWk1NbVJ3WkVkb01RcFphVFZxWWpJd2RtUklTbWhoVjNoMldtMUtjR1JJVFhaamJWcHFUMFJqTkU1VE5YZGxWRUUwUW1kdmNrSm5SVVZCV1U4dlRVRkZUa0pEYjAxTFJFVjVDbHBIV1ROUFJGVXhXV3BSZDFreVJtMU9ha1UxVG5wSmVFNVhTbWhhVjBwdFRtcEZlazFIVVRCWmFtTjVXbTFHYTAxRVRYZEpRVmxMUzNkWlFrSkJSMFFLZG5wQlFrUm5VVk5FUWtKNVdsZGFla3d6VW1oYU0wMTJaR3BCZFUxRE5IbE5RbXRIUTJselIwRlJVVUpuTnpoM1FWRTRSVU4zZDBwT2VsazBUV3BGZWdwUFZHc3pUVU0wUjBOcGMwZEJVVkZDWnpjNGQwRlNRVVZKUVhkbFlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVEROU2VWbFhiSE5pTWxwcENtRllVbnBOUW1OSFEybHpSMEZSVVVKbk56aDNRVkpGUlVOUmQwaE5hazE0VGtSUmVVMTZRbTlDWjI5eVFtZEZSVUZaVHk5TlFVVlRRa1p2VFZkSGFEQUtaRWhDZWs5cE9IWmFNbXd3WVVoV2FVeHRUblppVXprd1kyMUdjR0pIT1cxWmJXd3dZM2s1ZVZwdFRUUk9lbWN4VEc1Q05VeDVOVzVoV0ZKdlpGZEpkZ3BrTWpsNVlUSmFjMkl6WkhwTU0wcHNZa2RXYUdNeVZYVmxWekZ6VVVoS2JGcHVUWFprUjBadVkzazVNazFETkhkTWFrbDNUMEZaUzB0M1dVSkNRVWRFQ25aNlFVSkZkMUZ4UkVObmVFMXRVbTFPZW1jeFRsZEpNRTFIVG1oYWFsbDRUMVJqZVUxVVZtbFpWMVpwV21wWmVFMTZRbXRPUjBrelRXMWFhRnBFUVhvS1RVSmpSME5wYzBkQlVWRkNaemM0ZDBGU1VVVkRVWGRJWTIxV2MxcFhSbnBhVkVKalFtZHZja0puUlVWQldVOHZUVUZGVmtKRk5FMVVSMmd3WkVoQ2VncFBhVGgyV2pKc01HRklWbWxNYlU1MllsTTVNR050Um5CaVJ6bHRXVzFzTUdONU9YbGFiVTAwVG5wbk1VeHVRalZNTWtacVpFZHNkbUp1VFhaamJsWjFDbU41T0RSTlZHTTFUbXBuZVUxRVRUUk1Na1l3WkVkV2RHTklVbnBNZWtWM1JtZFpTMHQzV1VKQ1FVZEVkbnBCUWtablVVbEVRVnAzWkZkS2MyRlhUWGNLWjFsdlIwTnBjMGRCVVZGQ01XNXJRMEpCU1VWbVFWSTJRVWhuUVdSblJHUlFWRUp4ZUhOalVrMXRUVnBJYUhsYVducGpRMjlyY0dWMVRqUTRjbVlyU0FwcGJrdEJUSGx1ZFdwblFVRkJXVFJXTkhWWVkwRkJRVVZCZDBKSVRVVlZRMGxGYjFONmJEUlNkWHA2TW5jM2RqQXZWbFl4WWprMlJuQmtVRXMwZEhkekNuaDBUM2xtWkhKNVNYSnFhVUZwUlVFd1MwRjROSEkwV0cxaFFXOWpSa0Z0WTNvMUwxQXhOMFk0VDFSaFlucE9UbFJaTVdKV01UbG1lbGRyZDBObldVa0tTMjlhU1hwcU1FVkJkMDFFWVVGQmQxcFJTWGRJWmxVNVlqbElVVk50WTNCVWNqTnhSMVZpVTJWS1pHa3haa3AzUVRad1oyRTFaRTl5YmtGcFFtd3hWZ280ZWt0aFQzUkdlbkpIUTNWaGRsSnJNMXBHYmtGcVJVRXJjMUJsYlZwaVRuRnVObmt2UkhwVU5YQkRaMk5rUmpWc1JWZDJlRTlWUXpOaWN6QjVSMU53Q20weVJWWktSRWxJYkU5elRDdHVZWE15YVRscmRWcDVVUW90TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09In19fX0=" - } - ] - }, - "messageSignature": { - "messageDigest": { - "algorithm": "SHA2_256", - "digest": "ChhmZjQLV8HI82VCmgf1UmGhpgspV/Y7KUggxOPAteQ=" - }, - "signature": "MEUCIHIKWzSwwI62GqHdovcsWiW0KbNaHS0b42LBsxyRVNDrAiEA+tAKnG+vOfmzF5SfxBkFWnh7oGll5hOEizaWo+WXtvg=" - } -} \ No newline at end of file diff --git a/test/assets/rfc8785-0.1.2-py3-none-any.whl b/test/assets/rfc8785-0.1.2-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..00225acb8a344bb16015f9c172c21f3faa557f19 GIT binary patch literal 9172 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 a?LT*riUJh$KkQ-tTsME#W0ve6Z~qSo5WoQd literal 0 HcmV?d00001 diff --git a/test/assets/rfc8785-0.1.2-py3-none-any.whl.json b/test/assets/rfc8785-0.1.2-py3-none-any.whl.json new file mode 100644 index 0000000..bf2affa --- /dev/null +++ b/test/assets/rfc8785-0.1.2-py3-none-any.whl.json @@ -0,0 +1,49 @@ +{ + "version": 1, + "verification_material": { + "certificate": "MIIC1zCCAl2gAwIBAgIUZk9ToGFUJexy+/rxwIF8BB+3C5YwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjQwNDI5MTY1MTMzWhcNMjQwNDI5MTcwMTMzWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEM5H5f7A4HutVTfKFimTd2UbTzgUOY7rph9GKqgsZ7ChAp8FGJbrrgn6o+nprUEFKqEaIi+fWQJvR+RJkoQcWMKOCAXwwggF4MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUnrc9nJ2dxJd1a5sCFj/P+y3MuhQwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wLAYDVR0RAQH/BCIwIIEeZmFjdW5kby50dWVzY2FAdHJhaWxvZmJpdHMuY29tMCkGCisGAQQBg78wAQEEG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTArBgorBgEEAYO/MAEIBB0MG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABjyrE0sQAAAQDAEcwRQIhAORhP1HaCcD4QK8+8VcNL46W0AAk6cIDUAH3SV4stJUVAiBafyw+FTpgvoTU+2U7QCyjlQZ5J2dPpVqv9Up3vV2GTDAKBggqhkjOPQQDAwNoADBlAjEAzoA4cMHxHCEXA80ahwJUSz/1kYotTXRNzeWU69SyaZE7Po+vZ5/ANfKvbCv9s19rAjABbw/INkA4dGKWEDNtSjnloZuH5N9aPBOV425+iKCe2bmf9cYVlFvCbGmHiEg/r5k=", + "transparency_entries": [ + { + "logIndex": "89569370", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "hashedrekord", + "version": "0.0.1" + }, + "integratedTime": "1714409493", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIQC29r0j8BCu5Zye9dvFaVBmCFzHIDBDDWH+LqcZ8aTAyAIgas85UjhG4jrVwqBr/U/nQ86vwOWQnHKjGnd/bdnQafQ=" + }, + "inclusionProof": { + "logIndex": "85405939", + "rootHash": "CdYMKt8P8arrU1iilSLHbPDwMzhWgUbA6xvb1DSZktc=", + "treeSize": "85405941", + "hashes": [ + "btr1R1ZOzi0Kqk+vdfHrDcC1zasNMvXaNehse4NeMu8=", + "8IgEN8pEU3WrVRCsbbCkFHeamV5xoyN1OByng98lPow=", + "i6x3rMfR1HZCafUIGTyYgvtfwjF9zUe9Q5MPKNdWhS8=", + "kE6NsBxRpnT9Q/DgLDqQELBaor5pThUMmHIRuKapA7c=", + "Y55DSeWN5DUnIuvK5RRsaF4b35EtjKasFpV2n2LfrA0=", + "UeVeMpyn/bEywYJvThS5PltcrELznbc/OFTARixCNUQ=", + "MaMJLiuvSigqcgOZ6BulADPyhWaoYE1C+sGj/twciwM=", + "YrLY+ujALEUYcIeyq2ri+QBsl7Sxh+frMg7GlVcIvZ0=", + "27GLifvQI1aATtmSwJQGmbKXDoBpa0R5Q8fQUuX3/kQ=", + "xhLV7tE4kPldhHSKGpGuBkcxIUSpEvNntVSzM+5raW4=", + "btR5C6cRDz4AcGce5sOqhKIlEYTQ29AJLmv7L3kPyDI=", + "TuI0yJQvmNIs3J9pfzPMu2aYibKQ0MUpGgkcmjsS30g=", + "TxcrLS66touilnjU30hIZ8JkbH6bfnBbD6pQ5OoIpXs=", + "sjohk/3DQIfXTgf/5XpwtdF7yNbrf8YykOMHr1CyBYQ=", + "98enzMaC+x5oCMvIZQA5z8vu2apDMCFvE/935NfuPw8=" + ], + "checkpoint": { + "envelope": "rekor.sigstore.dev - 2605736670972794746\n85405941\nCdYMKt8P8arrU1iilSLHbPDwMzhWgUbA6xvb1DSZktc=\n\n— rekor.sigstore.dev wNI9ajBGAiEAkEVEjIsNbuvKywuzjow1tyD1IkIpHu/bCVK73fSpBzECIQD5ctzIS0Rp3cC3PF0ZcFEP8ObC2KJqojg4hfKjFxxy9A==\n" + } + }, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJjNGU5MmU5ZWNjODI4YmVmMmFhN2RiYTFkZThhYzk4MzUxMWY3NTMyYTBkZjExYzc3MGQzOTA5OWEyNWNmMjAxIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJSGlXY2JRY2szTzE2K3dGR3pyR09sYWVWRkpodkNwT1EwajZJd0ZtUnp0YUFpQWJWL3NOSWg0OFJQSHdIdm9IZklDcFA3Y29seGpjbUx6WEhsU2pleGEvUVE9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTXhla05EUVd3eVowRjNTVUpCWjBsVldtczVWRzlIUmxWS1pYaDVLeTl5ZUhkSlJqaENRaXN6UXpWWmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJkMDVFU1RWTlZGa3hUVlJOZWxkb1kwNU5hbEYzVGtSSk5VMVVZM2ROVkUxNlYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZOTlVnMVpqZEJORWgxZEZaVVprdEdhVzFVWkRKVllsUjZaMVZQV1RkeWNHZzVSMHNLY1dkeldqZERhRUZ3T0VaSFNtSnljbWR1Tm04cmJuQnlWVVZHUzNGRllVbHBLMlpYVVVwMlVpdFNTbXR2VVdOWFRVdFBRMEZZZDNkblowWTBUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZ1Y21NNUNtNUtNbVI0U21ReFlUVnpRMFpxTDFBcmVUTk5kV2hSZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDB4QldVUldVakJTUVZGSUwwSkRTWGRKU1VWbFdtMUdhbVJYTld0aWVUVXdaRmRXZWxreVJrRmtTRXBvWVZkNGRscHRTbkJrU0UxMVdUSTVkQXBOUTJ0SFEybHpSMEZSVVVKbk56aDNRVkZGUlVjeWFEQmtTRUo2VDJrNGRsbFhUbXBpTTFaMVpFaE5kVm95T1haYU1uaHNURzFPZG1KVVFYSkNaMjl5Q2tKblJVVkJXVTh2VFVGRlNVSkNNRTFITW1nd1pFaENlazlwT0haWlYwNXFZak5XZFdSSVRYVmFNamwyV2pKNGJFeHRUblppVkVOQ2FXZFpTMHQzV1VJS1FrRklWMlZSU1VWQloxSTRRa2h2UVdWQlFqSkJUakE1VFVkeVIzaDRSWGxaZUd0bFNFcHNiazUzUzJsVGJEWTBNMnA1ZEM4MFpVdGpiMEYyUzJVMlR3cEJRVUZDYW5seVJUQnpVVUZCUVZGRVFVVmpkMUpSU1doQlQxSm9VREZJWVVOalJEUlJTemdyT0ZaalRrdzBObGN3UVVGck5tTkpSRlZCU0ROVFZqUnpDblJLVlZaQmFVSmhabmwzSzBaVWNHZDJiMVJWS3pKVk4xRkRlV3BzVVZvMVNqSmtVSEJXY1hZNVZYQXpkbFl5UjFSRVFVdENaMmR4YUd0cVQxQlJVVVFLUVhkT2IwRkVRbXhCYWtWQmVtOUJOR05OU0hoSVEwVllRVGd3WVdoM1NsVlRlaTh4YTFsdmRGUllVazU2WlZkVk5qbFRlV0ZhUlRkUWJ5dDJXalV2UVFwT1prdDJZa04yT1hNeE9YSkJha0ZDWW5jdlNVNXJRVFJrUjB0WFJVUk9kRk5xYm14dlduVklOVTQ1WVZCQ1QxWTBNalVyYVV0RFpUSmliV1k1WTFsV0NteEdka05pUjIxSWFVVm5MM0kxYXowS0xTMHRMUzFGVGtRZ1EwVlNWRWxHU1VOQlZFVXRMUzB0TFFvPSJ9fX19" + } + ] + }, + "message_signature": "MEQCIHiWcbQck3O16+wFGzrGOlaeVFJhvCpOQ0j6IwFmRztaAiAbV/sNIh48RPHwHvoHfICpP7colxjcmLzXHlSjexa/QQ==" +} \ No newline at end of file diff --git a/test/assets/rfc8785-0.1.2-py3-none-any.whl.sigstore b/test/assets/rfc8785-0.1.2-py3-none-any.whl.sigstore new file mode 100644 index 0000000..290da36 --- /dev/null +++ b/test/assets/rfc8785-0.1.2-py3-none-any.whl.sigstore @@ -0,0 +1,57 @@ +{ + "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", + "verificationMaterial": { + "certificate": { + "rawBytes": "MIIC1zCCAl2gAwIBAgIUZk9ToGFUJexy+/rxwIF8BB+3C5YwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjQwNDI5MTY1MTMzWhcNMjQwNDI5MTcwMTMzWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEM5H5f7A4HutVTfKFimTd2UbTzgUOY7rph9GKqgsZ7ChAp8FGJbrrgn6o+nprUEFKqEaIi+fWQJvR+RJkoQcWMKOCAXwwggF4MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUnrc9nJ2dxJd1a5sCFj/P+y3MuhQwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wLAYDVR0RAQH/BCIwIIEeZmFjdW5kby50dWVzY2FAdHJhaWxvZmJpdHMuY29tMCkGCisGAQQBg78wAQEEG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTArBgorBgEEAYO/MAEIBB0MG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABjyrE0sQAAAQDAEcwRQIhAORhP1HaCcD4QK8+8VcNL46W0AAk6cIDUAH3SV4stJUVAiBafyw+FTpgvoTU+2U7QCyjlQZ5J2dPpVqv9Up3vV2GTDAKBggqhkjOPQQDAwNoADBlAjEAzoA4cMHxHCEXA80ahwJUSz/1kYotTXRNzeWU69SyaZE7Po+vZ5/ANfKvbCv9s19rAjABbw/INkA4dGKWEDNtSjnloZuH5N9aPBOV425+iKCe2bmf9cYVlFvCbGmHiEg/r5k=" + }, + "tlogEntries": [ + { + "logIndex": "89569370", + "logId": { + "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0=" + }, + "kindVersion": { + "kind": "hashedrekord", + "version": "0.0.1" + }, + "integratedTime": "1714409493", + "inclusionPromise": { + "signedEntryTimestamp": "MEUCIQC29r0j8BCu5Zye9dvFaVBmCFzHIDBDDWH+LqcZ8aTAyAIgas85UjhG4jrVwqBr/U/nQ86vwOWQnHKjGnd/bdnQafQ=" + }, + "inclusionProof": { + "logIndex": "85405939", + "rootHash": "CdYMKt8P8arrU1iilSLHbPDwMzhWgUbA6xvb1DSZktc=", + "treeSize": "85405941", + "hashes": [ + "btr1R1ZOzi0Kqk+vdfHrDcC1zasNMvXaNehse4NeMu8=", + "8IgEN8pEU3WrVRCsbbCkFHeamV5xoyN1OByng98lPow=", + "i6x3rMfR1HZCafUIGTyYgvtfwjF9zUe9Q5MPKNdWhS8=", + "kE6NsBxRpnT9Q/DgLDqQELBaor5pThUMmHIRuKapA7c=", + "Y55DSeWN5DUnIuvK5RRsaF4b35EtjKasFpV2n2LfrA0=", + "UeVeMpyn/bEywYJvThS5PltcrELznbc/OFTARixCNUQ=", + "MaMJLiuvSigqcgOZ6BulADPyhWaoYE1C+sGj/twciwM=", + "YrLY+ujALEUYcIeyq2ri+QBsl7Sxh+frMg7GlVcIvZ0=", + "27GLifvQI1aATtmSwJQGmbKXDoBpa0R5Q8fQUuX3/kQ=", + "xhLV7tE4kPldhHSKGpGuBkcxIUSpEvNntVSzM+5raW4=", + "btR5C6cRDz4AcGce5sOqhKIlEYTQ29AJLmv7L3kPyDI=", + "TuI0yJQvmNIs3J9pfzPMu2aYibKQ0MUpGgkcmjsS30g=", + "TxcrLS66touilnjU30hIZ8JkbH6bfnBbD6pQ5OoIpXs=", + "sjohk/3DQIfXTgf/5XpwtdF7yNbrf8YykOMHr1CyBYQ=", + "98enzMaC+x5oCMvIZQA5z8vu2apDMCFvE/935NfuPw8=" + ], + "checkpoint": { + "envelope": "rekor.sigstore.dev - 2605736670972794746\n85405941\nCdYMKt8P8arrU1iilSLHbPDwMzhWgUbA6xvb1DSZktc=\n\n\u2014 rekor.sigstore.dev wNI9ajBGAiEAkEVEjIsNbuvKywuzjow1tyD1IkIpHu/bCVK73fSpBzECIQD5ctzIS0Rp3cC3PF0ZcFEP8ObC2KJqojg4hfKjFxxy9A==\n" + } + }, + "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJjNGU5MmU5ZWNjODI4YmVmMmFhN2RiYTFkZThhYzk4MzUxMWY3NTMyYTBkZjExYzc3MGQzOTA5OWEyNWNmMjAxIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJSGlXY2JRY2szTzE2K3dGR3pyR09sYWVWRkpodkNwT1EwajZJd0ZtUnp0YUFpQWJWL3NOSWg0OFJQSHdIdm9IZklDcFA3Y29seGpjbUx6WEhsU2pleGEvUVE9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTXhla05EUVd3eVowRjNTVUpCWjBsVldtczVWRzlIUmxWS1pYaDVLeTl5ZUhkSlJqaENRaXN6UXpWWmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJkMDVFU1RWTlZGa3hUVlJOZWxkb1kwNU5hbEYzVGtSSk5VMVVZM2ROVkUxNlYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZOTlVnMVpqZEJORWgxZEZaVVprdEdhVzFVWkRKVllsUjZaMVZQV1RkeWNHZzVSMHNLY1dkeldqZERhRUZ3T0VaSFNtSnljbWR1Tm04cmJuQnlWVVZHUzNGRllVbHBLMlpYVVVwMlVpdFNTbXR2VVdOWFRVdFBRMEZZZDNkblowWTBUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZ1Y21NNUNtNUtNbVI0U21ReFlUVnpRMFpxTDFBcmVUTk5kV2hSZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDB4QldVUldVakJTUVZGSUwwSkRTWGRKU1VWbFdtMUdhbVJYTld0aWVUVXdaRmRXZWxreVJrRmtTRXBvWVZkNGRscHRTbkJrU0UxMVdUSTVkQXBOUTJ0SFEybHpSMEZSVVVKbk56aDNRVkZGUlVjeWFEQmtTRUo2VDJrNGRsbFhUbXBpTTFaMVpFaE5kVm95T1haYU1uaHNURzFPZG1KVVFYSkNaMjl5Q2tKblJVVkJXVTh2VFVGRlNVSkNNRTFITW1nd1pFaENlazlwT0haWlYwNXFZak5XZFdSSVRYVmFNamwyV2pKNGJFeHRUblppVkVOQ2FXZFpTMHQzV1VJS1FrRklWMlZSU1VWQloxSTRRa2h2UVdWQlFqSkJUakE1VFVkeVIzaDRSWGxaZUd0bFNFcHNiazUzUzJsVGJEWTBNMnA1ZEM4MFpVdGpiMEYyUzJVMlR3cEJRVUZDYW5seVJUQnpVVUZCUVZGRVFVVmpkMUpSU1doQlQxSm9VREZJWVVOalJEUlJTemdyT0ZaalRrdzBObGN3UVVGck5tTkpSRlZCU0ROVFZqUnpDblJLVlZaQmFVSmhabmwzSzBaVWNHZDJiMVJWS3pKVk4xRkRlV3BzVVZvMVNqSmtVSEJXY1hZNVZYQXpkbFl5UjFSRVFVdENaMmR4YUd0cVQxQlJVVVFLUVhkT2IwRkVRbXhCYWtWQmVtOUJOR05OU0hoSVEwVllRVGd3WVdoM1NsVlRlaTh4YTFsdmRGUllVazU2WlZkVk5qbFRlV0ZhUlRkUWJ5dDJXalV2UVFwT1prdDJZa04yT1hNeE9YSkJha0ZDWW5jdlNVNXJRVFJrUjB0WFJVUk9kRk5xYm14dlduVklOVTQ1WVZCQ1QxWTBNalVyYVV0RFpUSmliV1k1WTFsV0NteEdka05pUjIxSWFVVm5MM0kxYXowS0xTMHRMUzFGVGtRZ1EwVlNWRWxHU1VOQlZFVXRMUzB0TFFvPSJ9fX19" + } + ] + }, + "messageSignature": { + "messageDigest": { + "algorithm": "SHA2_256", + "digest": "xOkunsyCi+8qp9uh3orJg1EfdTKg3xHHcNOQmaJc8gE=" + }, + "signature": "MEQCIHiWcbQck3O16+wFGzrGOlaeVFJhvCpOQ0j6IwFmRztaAiAbV/sNIh48RPHwHvoHfICpP7colxjcmLzXHlSjexa/QQ==" + } +} diff --git a/test/test_impl.py b/test/test_impl.py index 293e7b6..ab7d70a 100644 --- a/test/test_impl.py +++ b/test/test_impl.py @@ -5,63 +5,78 @@ import pypi_attestation_models._impl as impl import pytest -from sigstore_protobuf_specs.dev.sigstore.bundle.v1 import Bundle +from sigstore.models import Bundle +from sigstore.verify import Verifier, policy -bundle_path = Path(__file__).parent / "assets" / "rfc8785-0.0.2-py3-none-any.whl.sigstore" -attestation_path = Path(__file__).parent / "assets" / "rfc8785-0.0.2-py3-none-any.whl.json" +artifact_path = Path(__file__).parent / "assets" / "rfc8785-0.1.2-py3-none-any.whl" +bundle_path = Path(__file__).parent / "assets" / "rfc8785-0.1.2-py3-none-any.whl.sigstore" +attestation_path = Path(__file__).parent / "assets" / "rfc8785-0.1.2-py3-none-any.whl.json" def test_sigstore_to_pypi() -> None: + # Load an existing Sigstore bundle, convert it to a PyPI attestation, + # and check that the result is what we expect. with bundle_path.open("rb") as f: - sigstore_bundle = Bundle().from_json(f.read()) + sigstore_bundle = Bundle.from_json(f.read()) attestation = impl.sigstore_to_pypi(sigstore_bundle) with attestation_path.open("rb") as expected_file: - assert json.loads(attestation.to_json()) == json.load(expected_file) - - -def test_sigstore_to_pypi_empty_certs() -> None: - with bundle_path.open("rb") as f: - sigstore_bundle = Bundle().from_json(f.read()) - sigstore_bundle.verification_material.certificate.raw_bytes = b"" - sigstore_bundle.verification_material.x509_certificate_chain.certificates = [] - - with pytest.raises(impl.InvalidBundleError): - impl.sigstore_to_pypi(sigstore_bundle) + assert json.loads(attestation.model_dump_json()) == json.load(expected_file) def test_pypi_to_sigstore() -> None: + # Load an existing PyPI attestation, convert it to a Sigstore bundle, + # and check that the result matches the original Sigstore bundle used + # to generate the attestation with attestation_path.open("rb") as f: - attestation = impl.Attestation.from_dict(json.load(f)) + attestation = impl.Attestation.model_validate_json(f.read()) bundle = impl.pypi_to_sigstore(attestation) with bundle_path.open("rb") as original_bundle_file: - original_bundle = Bundle().from_json(original_bundle_file.read()) + original_bundle = Bundle.from_json(original_bundle_file.read()) # Sigstore Bundle -> PyPI attestation is a lossy operation, so when we go backwards - # the resulting Bundle will have fewer fields than the original Bundle. Not only that, - # but the fields present might be different (e.g: the original bundle might have a - # `x509_certificate_chain` field, but the converted bundle will use the `certificate` field - # instead). - assert bundle.media_type == "application/vnd.dev.sigstore.bundle+json;version=0.3" - assert bundle.message_signature.signature == original_bundle.message_signature.signature + # the resulting Bundle will have fewer fields than the original Bundle. + assert bundle._inner.media_type == original_bundle._inner.media_type # noqa: SLF001 + assert bundle._inner.verification_material == original_bundle._inner.verification_material # noqa: SLF001 assert ( - bundle.verification_material.tlog_entries - == original_bundle.verification_material.tlog_entries + bundle._inner.message_signature.signature # noqa: SLF001 + == original_bundle._inner.message_signature.signature # noqa: SLF001 ) - if original_bundle.verification_material.certificate.raw_bytes != b"": - assert ( - bundle.verification_material.certificate - == original_bundle.verification_material.certificate - ) - else: - assert ( - bundle.verification_material.certificate - == original_bundle.verification_material.x509_certificate_chain.certificates[0] - ) + assert bundle.log_entry == original_bundle.log_entry + assert bundle.signing_certificate == original_bundle.signing_certificate def test_pypi_to_sigstore_invalid_certificate_base64() -> None: with attestation_path.open("rb") as f: - attestation = impl.Attestation.from_dict(json.load(f)) + attestation = impl.Attestation.model_validate_json(f.read()) attestation.verification_material.certificate = "invalid base64 @@@@ string" with pytest.raises(impl.InvalidAttestationError): impl.pypi_to_sigstore(attestation) + + +def test_verification_roundtrip() -> None: + # Load an existing Sigstore bundle, check that verification passes, + # convert it to a PyPI attestation and then back again to a Sigstore + # bundle, and check that verification still passes. + with bundle_path.open("rb") as f: + sigstore_bundle = Bundle.from_json(f.read()) + + verifier = Verifier.production() + with artifact_path.open("rb") as f: + verifier.verify_artifact( + f.read(), + sigstore_bundle, + policy.Identity( + identity="facundo.tuesca@trailofbits.com", issuer="https://accounts.google.com" + ), + ) + + attestation = impl.sigstore_to_pypi(sigstore_bundle) + roundtrip_bundle = impl.pypi_to_sigstore(attestation) + with artifact_path.open("rb") as f: + verifier.verify_artifact( + f.read(), + roundtrip_bundle, + policy.Identity( + identity="facundo.tuesca@trailofbits.com", issuer="https://accounts.google.com" + ), + )