diff --git a/pyproject.toml b/pyproject.toml index 93bd7bf..495f57b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,14 +8,14 @@ version = "1.1.0" description = "CLI key-authorization manager for envelope_crypto" requires-python = ">=3.10" dependencies = [ - "envelope_crypto @ git+https://git.rethinkstudios.io/rethink-public/envelope_crypto.git@v1.0.0", + "envelope_crypto @ git+https://git.rethinkstudios.io/rethink-public/envelope_crypto.git@v1.1.0", "cryptography>=42.0", "tomli>=2.0; python_version<'3.11'", ] [project.optional-dependencies] mongo = [ - "mongo @ git+https://git.rethinkstudios.io/rethink-public/mongo.git@v1.0.0", + "mongo @ git+https://git.rethinkstudios.io/rethink-public/mongo.git@v1.1.0", ] [project.scripts] diff --git a/src/envelope_authorizer/commands/list_keys.py b/src/envelope_authorizer/commands/list_keys.py index e52f2c1..e720a79 100644 --- a/src/envelope_authorizer/commands/list_keys.py +++ b/src/envelope_authorizer/commands/list_keys.py @@ -9,6 +9,7 @@ import logging from datetime import datetime, timezone from cryptography.exceptions import InvalidTag +from envelope_crypto import KeyMismatchError from . import boot_local, doc_meta, read_flag @@ -18,13 +19,20 @@ log = logging.getLogger(__name__) def _can_authorize(crypto, doc) -> str: """decrypted authority of a doc as Yes/No, or `?` if unreadable here - a malformed/foreign flag degrades to `?` for display continuity. a GCM auth-tag - failure is logged first (WARNING): it is either a foreign key this host can't - decrypt or a tampered authz record, and this layer can't tell them apart, so the - security signal must stay visible rather than render identically to a `?`. + a malformed flag degrades to `?` silently. a flag that can't be read here is + logged first (WARNING) so the security signal stays visible rather than render + identically to a `?`: a kid mismatch means it was sealed under another key; a GCM + auth-tag failure (no kid, pre-1.1.0 flag) is a foreign key or a tampered record + and this layer can't tell them apart. """ try: return "Yes" if read_flag(crypto, doc["meta"]["authorizer"]) else "No" + except KeyMismatchError as error: + friendly = doc_meta(doc).get("friendly", doc.get("_id", "?")) + log.warning( + "flag %s sealed under another key (key id %s, loaded %s)", friendly, error.blob_kid, error.key_kid, + ) + return "?" except (KeyError, TypeError, ValueError): return "?" except InvalidTag: