Skip to content

deps: bump protobuf-specs #1276

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ dependencies = [
"rfc8785 ~= 0.1.2",
"rfc3161-client >= 0.1.2,< 1.1.0",
# NOTE(ww): Both under active development, so strictly pinned.
"sigstore-protobuf-specs == 0.3.2",
"sigstore-protobuf-specs == 0.3.5",
"sigstore-rekor-types == 0.0.18",
"tuf ~= 6.0",
"platformdirs ~= 4.2",
Expand Down
6 changes: 2 additions & 4 deletions sigstore/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -713,9 +713,7 @@ def _sign_common(
else:
sig_output = sys.stdout

signature = base64.b64encode(
result._inner.message_signature.signature
).decode()
Comment on lines -716 to -718
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NB: This was previously just wrong for DSSE outputs, but we didn't notice since nothing really uses the --signature flag anymore.

signature = base64.b64encode(result.signature).decode()
print(signature, file=sig_output)
if outputs.signature is not None:
print(f"Signature written to {outputs.signature}")
Expand Down Expand Up @@ -1202,7 +1200,7 @@ def _fix_bundle(args: argparse.Namespace) -> None:
# for custom Rekor instances.
rekor = RekorClient.staging() if args.staging else RekorClient.production()

raw_bundle = RawBundle().from_json(args.bundle.read_text())
raw_bundle = RawBundle.from_dict(json.loads(args.bundle.read_bytes()))

if len(raw_bundle.verification_material.tlog_entries) != 1:
_fatal("unfixable bundle: must have exactly one log entry")
Expand Down
4 changes: 2 additions & 2 deletions sigstore/_internal/trust.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ class Key:
key: PublicKey
key_id: KeyID

_RSA_SHA_256_DETAILS: ClassVar[set[_PublicKeyDetails]] = {
_RSA_SHA_256_DETAILS: ClassVar = {
_PublicKeyDetails.PKCS1_RSA_PKCS1V5,
_PublicKeyDetails.PKIX_RSA_PKCS1V15_2048_SHA256,
_PublicKeyDetails.PKIX_RSA_PKCS1V15_3072_SHA256,
_PublicKeyDetails.PKIX_RSA_PKCS1V15_4096_SHA256,
}

_EC_DETAILS_TO_HASH: ClassVar[dict[_PublicKeyDetails, hashes.HashAlgorithm]] = {
_EC_DETAILS_TO_HASH: ClassVar = {
_PublicKeyDetails.PKIX_ECDSA_P256_SHA_256: hashes.SHA256(),
_PublicKeyDetails.PKIX_ECDSA_P384_SHA_384: hashes.SHA384(),
_PublicKeyDetails.PKIX_ECDSA_P521_SHA_512: hashes.SHA512(),
Expand Down
2 changes: 1 addition & 1 deletion sigstore/hashes.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ def __str__(self) -> str:
"""
Returns a str representation of this `Hashed`.
"""
return f"{self.algorithm.name}:{self.digest.hex()}"
return f"{HashAlgorithm(self.algorithm)}:{self.digest.hex()}"
66 changes: 36 additions & 30 deletions sigstore/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from __future__ import annotations

import base64
import json
import logging
import typing
from enum import Enum
Expand Down Expand Up @@ -466,18 +467,18 @@ def _verify(self) -> None:
Bundle.BundleType.BUNDLE_0_3_ALT,
):
# For "v3" bundles, the signing certificate is the only one present.
if not self._inner.verification_material.certificate:
raise InvalidBundle("expected certificate in bundle")

leaf_cert = load_der_x509_certificate(
self._inner.verification_material.certificate.raw_bytes
)
else:
# In older bundles, there is an entire pool (misleadingly called
# a chain) of certificates, the first of which is the signing
# certificate.
certs = (
self._inner.verification_material.x509_certificate_chain.certificates
)

if len(certs) == 0:
chain = self._inner.verification_material.x509_certificate_chain
if not chain or not chain.certificates:
raise InvalidBundle("expected non-empty certificate chain in bundle")

# Per client policy in protobuf-specs: the first entry in the chain
Expand All @@ -489,7 +490,7 @@ def _verify(self) -> None:
# and intermediate CAs, so we issue warnings and not hard errors
# in those cases.
leaf_cert, *chain_certs = [
load_der_x509_certificate(cert.raw_bytes) for cert in certs
load_der_x509_certificate(cert.raw_bytes) for cert in chain.certificates
]
if not cert_is_leaf(leaf_cert):
raise InvalidBundle(
Expand Down Expand Up @@ -576,8 +577,8 @@ def _dsse_envelope(self) -> dsse.Envelope | None:

@private
"""
if self._inner.dsse_envelope:
return dsse.Envelope(self._inner.dsse_envelope)
if self._inner.is_set("dsse_envelope"):
return dsse.Envelope(self._inner.dsse_envelope) # type: ignore[arg-type]
return None

@property
Expand All @@ -589,7 +590,7 @@ def signature(self) -> bytes:
return (
self._dsse_envelope.signature
if self._dsse_envelope
else self._inner.message_signature.signature
else self._inner.message_signature.signature # type: ignore[union-attr]
)

@property
Expand All @@ -604,7 +605,7 @@ def from_json(cls, raw: bytes | str) -> Bundle:
"""
Deserialize the given Sigstore bundle.
"""
inner = _Bundle().from_json(raw)
inner = _Bundle.from_dict(json.loads(raw))
return cls(inner)

def to_json(self) -> str:
Expand All @@ -623,7 +624,10 @@ def _to_parts(
"""

content: common_v1.MessageSignature | dsse.Envelope
content = self._dsse_envelope or self._inner.message_signature
if self._dsse_envelope:
content = self._dsse_envelope
else:
content = self._inner.message_signature # type: ignore[assignment]

return (self.signing_certificate, content, self.log_entry)

Expand All @@ -650,30 +654,32 @@ def _from_parts(
@private
"""

inner = _Bundle(
media_type=Bundle.BundleType.BUNDLE_0_3.value,
verification_material=bundle_v1.VerificationMaterial(
certificate=common_v1.X509Certificate(cert.public_bytes(Encoding.DER)),
),
timestamp_verifcation_data = bundle_v1.TimestampVerificationData(
rfc3161_timestamps=[]
)
if signed_timestamp is not None:
timestamp_verifcation_data.rfc3161_timestamps.extend(
[
Rfc3161SignedTimestamp(signed_timestamp=response.as_bytes())
for response in signed_timestamp
]
)

# Fill in the appropriate variants.
if isinstance(content, common_v1.MessageSignature):
inner.message_signature = content
# mypy will be mystified if types are specified here
content_dict: dict[str, Any] = {"message_signature": content}
else:
inner.dsse_envelope = content._inner
content_dict = {"dsse_envelope": content._inner}

tlog_entry = log_entry._to_rekor()
inner.verification_material.tlog_entries = [tlog_entry]

if signed_timestamp is not None:
inner.verification_material.timestamp_verification_data = (
bundle_v1.TimestampVerificationData(
rfc3161_timestamps=[
Rfc3161SignedTimestamp(signed_timestamp=response.as_bytes())
for response in signed_timestamp
]
)
)
inner = _Bundle(
media_type=Bundle.BundleType.BUNDLE_0_3.value,
verification_material=bundle_v1.VerificationMaterial(
certificate=common_v1.X509Certificate(cert.public_bytes(Encoding.DER)),
tlog_entries=[log_entry._to_rekor()],
timestamp_verification_data=timestamp_verifcation_data,
),
**content_dict,
)

return cls(inner)
4 changes: 2 additions & 2 deletions sigstore/verify/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ def verify_artifact(
signing_key = bundle.signing_certificate.public_key()
signing_key = cast(ec.EllipticCurvePublicKey, signing_key)
signing_key.verify(
bundle._inner.message_signature.signature,
bundle._inner.message_signature.signature, # type: ignore[union-attr]
hashed_input.digest,
ec.ECDSA(hashed_input._as_prehashed()),
)
Expand All @@ -515,7 +515,7 @@ def verify_artifact(

expected_body = _hashedrekord_from_parts(
bundle.signing_certificate,
bundle._inner.message_signature.signature,
bundle._inner.message_signature.signature, # type: ignore[union-attr]
hashed_input,
)
actual_body = rekor_types.Hashedrekord.model_validate_json(
Expand Down