# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference) # Canonical Residual: https://corpusfetch.com/c/what-signature-downgrade-invariants-prevent-agents-from-accepting-weaker-cryptographic-proofs-when-upgraded-proofs-fail.md # Remnant Warrant: https://corpusfetch.com/c/what-signature-downgrade-invariants-prevent-agents-from-accepting-weaker-cryptographic-proofs-when-upgraded-proofs-fail.warrant.json # Markdown SHA-256: 2bbfeab04b9ccd07bee3752f468d1f8f5e58544534ae38d3c83fd154667c9f72 # Code AST SHA-256: 848370895d98da3084c491756061372c3af2ffa619a650689e8d7a26d878769a # Verified Classes: SignatureVerdict, Signature, SignatureRequirements, SignaturePolicy, SignatureManifest, DowngradeGuard # Defensive Guards: 0 fail-closed invariants (zero external deps) from dataclasses import dataclass from enum import Enum, auto import hashlib import json class SignatureVerdict(Enum): STRENGTH_REQUIREMENT_MET = auto() DOWNGRADE_REJECTED = auto() HYBRID_INCOMPLETE = auto() ALGORITHM_CONFUSION = auto() @dataclass(frozen=True) class Signature: signature_id: str algorithm: str key_size: int is_hybrid: bool hybrid_components_present: int signature_epoch: float @dataclass(frozen=True) class SignatureRequirements: required_algorithm: str required_key_size: int require_hybrid: bool current_authoritative_epoch: float @dataclass(frozen=True) class SignaturePolicy: require_exact_algorithm: bool @dataclass(frozen=True) class SignatureManifest: verdict: SignatureVerdict directive: str manifest_digest: str class DowngradeGuard: @staticmethod def _hash(data: str) -> str: return hashlib.sha256(data.encode("utf-8")).hexdigest() @classmethod def evaluate_signature( cls, sig: Signature, reqs: SignatureRequirements, policy: SignaturePolicy ) -> SignatureManifest: # Gate 1: Hybrid requirement if reqs.require_hybrid and sig.is_hybrid: if sig.hybrid_components_present < 2: return SignatureManifest( verdict=SignatureVerdict.HYBRID_INCOMPLETE, directive=f"HALT: Hybrid signature {sig.signature_id} has {sig.hybrid_components_present}/2 components. Downgrade attack.", manifest_digest=cls._hash(f"HYBRID_INCOMPLETE:{sig.signature_id}") ) if reqs.require_hybrid and not sig.is_hybrid: return SignatureManifest( verdict=SignatureVerdict.DOWNGRADE_REJECTED, directive=f"HALT: Signature {sig.signature_id} is not hybrid but hybrid required.", manifest_digest=cls._hash(f"NOT_HYBRID:{sig.signature_id}") ) # Gate 2: Algorithm check if policy.require_exact_algorithm: if sig.algorithm != reqs.required_algorithm: return SignatureManifest( verdict=SignatureVerdict.ALGORITHM_CONFUSION, directive=f"HALT: Signature {sig.signature_id} algorithm {sig.algorithm} != required {reqs.required_algorithm}.", manifest_digest=cls._hash(f"ALGO:{sig.signature_id}") ) # Gate 3: Key size if sig.key_size < reqs.required_key_size: return SignatureManifest( verdict=SignatureVerdict.DOWNGRADE_REJECTED, directive=f"HALT: Signature {sig.signature_id} key size {sig.key_size} < {reqs.required_key_size}.", manifest_digest=cls._hash(f"KEY_SIZE:{sig.signature_id}") ) # Gate 4: Epoch check (for rotation) if sig.signature_epoch < reqs.current_authoritative_epoch: return SignatureManifest( verdict=SignatureVerdict.DOWNGRADE_REJECTED, directive=f"HALT: Signature {sig.signature_id} epoch {sig.signature_epoch:.0f} predates current authoritative {reqs.current_authoritative_epoch:.0f}.", manifest_digest=cls._hash(f"STALE_EPOCH:{sig.signature_id}") ) # Gate 5: Meets requirements digest = cls._hash(json.dumps({ "signature": sig.signature_id, "algorithm": sig.algorithm, "key_size": str(sig.key_size), "hybrid": str(sig.is_hybrid), "epoch": f"{sig.signature_epoch:.0f}" }, sort_keys=True)) return SignatureManifest( verdict=SignatureVerdict.STRENGTH_REQUIREMENT_MET, directive=f"PROCEED: Signature {sig.signature_id} meets strength requirements.", manifest_digest=digest )