Skip to content

Commit

Permalink
sct, keyring: specialize errors (#555)
Browse files Browse the repository at this point in the history
* sct, keyring: specialize errors

Signed-off-by: Andrew Pan <a@tny.town>

* CHANGELOG: blurb for SCT changes

Signed-off-by: Andrew Pan <a@tny.town>

* CHANGELOG: add ref to PR

Signed-off-by: Andrew Pan <a@tny.town>

* Apply suggestions from code review

Signed-off-by: Andrew Pan <a@tny.town>

---------

Signed-off-by: Andrew Pan <a@tny.town>
  • Loading branch information
tnytown authored Mar 17, 2023
1 parent d0bf36a commit dddbf4e
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ All versions prior to 0.9.0 are untracked.
([#535](https://github.com/sigstore/sigstore-python/pull/535))
* Revamped error diagnostics reporting. All errors with diagnostics now implement
`sigstore.errors.Error`.
* Improved diagnostics around Signed Certificate Timestamp verification failures.
([#555](https://github.com/sigstore/sigstore-python/pull/555))

### Fixed

Expand Down
8 changes: 7 additions & 1 deletion sigstore/_internal/keyring.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ class KeyringLookupError(KeyringError):
pass


class KeyringSignatureError(KeyringError):
"""
Raised when `Keyring.verify()` is passed an invalid signature.
"""


class Keyring:
"""
Represents a set of CT signing keys, each of which is a potentially
Expand Down Expand Up @@ -101,4 +107,4 @@ def verify(self, *, key_id: KeyID, signature: bytes, data: bytes) -> None:
# NOTE(ww): Unreachable without API misuse.
raise KeyringError(f"unsupported key type: {key}")
except InvalidSignature as exc:
raise KeyringError("invalid signature") from exc
raise KeyringSignatureError("invalid signature") from exc
69 changes: 56 additions & 13 deletions sigstore/_internal/sct.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@
from cryptography.x509.oid import ExtendedKeyUsageOID

from sigstore._internal.ctfe import CTKeyring
from sigstore._internal.keyring import KeyringError, KeyringLookupError
from sigstore._internal.keyring import (
KeyringError,
KeyringLookupError,
KeyringSignatureError,
)
from sigstore._utils import DERCert, KeyID, key_id
from sigstore.errors import Error

Expand Down Expand Up @@ -142,13 +146,34 @@ class InvalidSCTError(Error):

def diagnostics(self) -> str:
"""Returns diagnostics for the error."""
# We specialize this error case, since it usually indicates one of
# two conditions: either the current sigstore client is out-of-date,
# or that the SCT is well-formed but invalid for the current configuration
# (indicating that the user has asked for the wrong instance).
if isinstance(self.__cause__, KeyringLookupError):
return dedent(
f"""

ctx = f"\nContext: {self.__context__}" if self.__context__ else ""
return dedent(
f"""
SCT verification failed.
Additional context:
Message: {str(self)}
"""
+ ctx
)


class InvalidSCTKeyError(InvalidSCTError):
"""
Raised during SCT verification if the SCT can't be validated against the given keyring.
We specialize this error case, since it usually indicates one of
two conditions: either the current sigstore client is out-of-date,
or that the SCT is well-formed but invalid for the current configuration
(indicating that the user has asked for the wrong instance).
"""

def diagnostics(self) -> str:
"""Returns diagnostics for the error."""
return dedent(
f"""
Invalid key ID in SCT: not found in current keyring.
This may be a result of an outdated `sigstore` installation.
Expand All @@ -161,9 +186,27 @@ def diagnostics(self) -> str:
{self.__cause__}
"""
)
)

return str(self)

class SCTSignatureError(InvalidSCTError):
"""
Raised during SCT verification if the signature of the SCT is invalid.
"""

def diagnostics(self) -> str:
"""Returns diagnostics for the error."""
return dedent(
f"""
Invalid signature on SCT.
If validating a certificate, the certificate associated with this SCT should not be trusted.
Additional context:
{self.__cause__}
"""
)


def verify_sct(
Expand Down Expand Up @@ -214,8 +257,8 @@ def verify_sct(
key_id=KeyID(sct.log_id), signature=sct.signature, data=digitally_signed
)
except KeyringLookupError as exc:
raise InvalidSCTError(
"Invalid key ID in SCT: not found in current keyring"
) from exc
raise InvalidSCTKeyError from exc
except KeyringSignatureError as exc:
raise SCTSignatureError from exc
except KeyringError as exc:
raise InvalidSCTError from exc

0 comments on commit dddbf4e

Please sign in to comment.