Skip to content

Commit 5b3d8e9

Browse files
committed
sigstore/verify: cleanup, inclusion proof logic
Always perform the inclusion proof opportunistically, even if the proof it provides is no stronger than the inclusion promise. Signed-off-by: William Woodruff <[email protected]>
1 parent 719299c commit 5b3d8e9

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

sigstore/verify/models.py

+24-7
Original file line numberDiff line numberDiff line change
@@ -259,16 +259,17 @@ def from_bundle(
259259
)
260260
tlog_entry = tlog_entries[0]
261261

262-
# NOTE: We only load the inclusion proof from the bundle if we know that
263-
# we're performing an offline verification, since that's the only case
264-
# in which we'll use it.
262+
# NOTE: Bundles are not required to include inclusion proofs,
263+
# since offline (or non-gossiped) verification of an inclusion proof is
264+
# only as strong as verification of the inclusion promise, which
265+
# is always provided.
265266
inclusion_proof = tlog_entry.inclusion_proof
266267
parsed_inclusion_proof: LogInclusionProof | None = None
267-
if inclusion_proof and offline:
268+
if inclusion_proof:
268269
checkpoint = inclusion_proof.checkpoint
269270

270-
# If the bundle to be verified offline includes an inclusion proof,
271-
# we verify it, which requires a checkpoint.
271+
# If the inclusion proof is provided, it must include its
272+
# checkpoint.
272273
if not checkpoint.envelope:
273274
raise InvalidMaterials("expected checkpoint in inclusion proof")
274275

@@ -316,8 +317,23 @@ def rekor_entry(self, client: RekorClient) -> LogEntry:
316317
"""
317318
Returns a `RekorEntry` for the current signing materials.
318319
"""
320+
321+
# The Rekor entry we use depends on a few different states:
322+
# 1. If the user has requested offline verification and we've
323+
# been given an offline Rekor entry to use, we use it.
324+
# 2. If the user has not requested offline verification,
325+
# we *opportunistically* use the offline Rekor entry,
326+
# so long as it contains an inclusion proof. If it doesn't
327+
# contain an inclusion proof, then we do an online entry lookup.
328+
329+
offline = self._offline
330+
has_rekor_entry = self.has_rekor_entry
331+
has_inclusion_proof = (
332+
self.has_rekor_entry and self._rekor_entry.inclusion_proof is not None
333+
)
334+
319335
entry: LogEntry | None
320-
if self._offline and self.has_rekor_entry:
336+
if (offline and has_rekor_entry) or (not offline and has_inclusion_proof):
321337
logger.debug("using offline rekor entry")
322338
entry = self._rekor_entry
323339
else:
@@ -328,6 +344,7 @@ def rekor_entry(self, client: RekorClient) -> LogEntry:
328344
self.certificate,
329345
)
330346

347+
# No matter what we do above, we must end up with a Rekor entry.
331348
if entry is None:
332349
raise RekorEntryMissing
333350

sigstore/verify/verifier.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -266,16 +266,14 @@ def verify(
266266
return VerificationFailure(reason=f"invalid Rekor root hash: {exc}")
267267

268268
logger.debug("Successfully verified inclusion proof...")
269-
270-
# Paranoia: if this is an online verification, we should *always* have
271-
# an inclusion proof, as we retrieved the log entry from Rekor. This
272-
# is an invalid state, so fail.
273269
elif not materials._offline:
270+
# Paranoia: if we weren't given an inclusion proof, then
271+
# this *must* have been offline verification. If it was online
272+
# then we've somehow entered an invalid state, so fail.
274273
return VerificationFailure(reason="missing Rekor inclusion proof")
275274
else:
276-
logger.debug(
277-
"inclusion proof not present in offline bundle: skipping Merkle "
278-
"inclusion proof verification"
275+
logger.warning(
276+
"inclusion proof not present in bundle: skipping due to offline verification"
279277
)
280278

281279
# 6) Verify the Signed Entry Timestamp (SET) supplied by Rekor for this artifact

0 commit comments

Comments
 (0)