pub struct KeyRevocation {
pub revoked_key_fingerprint: String,
pub compromised_since: DateTime<Utc>,
pub reason: Option<String>,
pub revoked_key_id: Option<String>,
pub revoked_key_controller: AgentDid,
pub publisher: AgentDid,
pub trust_class: RevocationTrustClass,
}Expand description
Typed, shape-validated view of a key-revocation context body
(RFC-ACDP-0014 §4).
Obtain via KeyRevocation::from_body. Field semantics:
- The fingerprint is authoritative;
revoked_key_idis human traceability only (§4). compromised_sinceis the compromise boundary T: signatures made strictly before T are attributable to the producer; at or after T they are not (§7). Across a superseding revocation lineage the earliest T is effective (§4,effective_boundary).- A revocation is permanent — there is no un-revoking. Consumers SHOULD cache verified revocations indefinitely (§7); the type is serde-serializable for exactly that.
Fields§
§revoked_key_fingerprint: StringRFC-ACDP-0010 §6 fingerprint of the revoked public key
(sha256: + 64 lowercase hex), byte-for-byte the encoding
receipts record. Authoritative over revoked_key_id.
compromised_since: DateTime<Utc>The compromise boundary T (canonical millisecond RFC 3339 UTC on the wire).
reason: Option<String>Optional human-readable circumstances (≤ 1024 chars). Informational only — apply output hygiene before display (RFC-ACDP-0014 §13).
revoked_key_id: Option<String>Optional DID URL of the revoked verification method. On any disagreement with the fingerprint, the fingerprint governs.
revoked_key_controller: AgentDidThe producer DID that controls the revoked key. Defaults to the
body’s agent_id when the metadata field is absent
(producer-signed form); on registry-attested revocations it
names the affected producer while agent_id is the registry.
publisher: AgentDidThe body’s agent_id — the identity the revocation was
published under (the producer for RevocationTrustClass::ProducerSigned,
the registry for RevocationTrustClass::RegistryAttested).
trust_class: RevocationTrustClass§5/§6 trust class, derived from the controller binding:
revoked_key_controller absent or equal to agent_id ⇒
producer-signed; different ⇒ registry-attested. MUST NOT be
collapsed when reporting (§6). For a registry-attested claim the
caller still owns confirming that publisher really is the DID
of a registry it talks to — see
Self::cross_check_registry_binding.
Implementations§
Source§impl KeyRevocation
impl KeyRevocation
Sourcepub fn from_body(body: &Body) -> Result<Self, AcdpError>
pub fn from_body(body: &Body) -> Result<Self, AcdpError>
Parse and shape-validate a key-revocation context body per
RFC-ACDP-0014 §4.
Enforced here (violations are AcdpError::SchemaViolation, the
code a 0.3.0 registry rejects them with at publish):
typeiskey-revocation(or the §10 interimacdp:key-revocation).visibilityispublic— an audience-restricted revocation protects nobody outside the audience.metadata.revoked_key_fingerprintpresent, in the RFC-ACDP-0010 §6 formsha256:+ 64 lowercase hex.metadata.compromised_sincepresent, canonical millisecond-precision RFC 3339 UTC (RFC-ACDP-0001 §5.3).metadata.reason, when present, ≤ 1024 characters.metadata.revoked_key_controller, when present, a valid DID.
Additionally, when the signing key’s fingerprint is derivable
purely from the body (a did:key signer), the §5 step 2
not-self-signed rule is enforced here too. For did:web signers
the fingerprint requires DID resolution: callers MUST follow up
with Self::check_not_self_signed against the resolved
fingerprint (acdp-client’s revocation pipeline does).
This does NOT verify the body’s hash or signature — a parsed revocation is untrusted until the strict §5.11 pipeline passes.
Sourcepub fn from_publish_request(req: &PublishRequest) -> Result<Self, AcdpError>
pub fn from_publish_request(req: &PublishRequest) -> Result<Self, AcdpError>
Parse and shape-validate a key-revocation context carried as a
producer-submitted PublishRequest — i.e. before the registry
has assigned ctx_id/lineage_id/origin_registry/created_at.
Enforces exactly the same RFC-ACDP-0014 §4 shape table as
Self::from_body (see its doc comment for the itemized list),
because none of those checks touch a registry-assigned field.
This is the entry point a PublishValidator — which sees a
PublishRequest, never a Body — uses to run the §4 checks at
publish time.
Sourcepub fn check_not_self_signed(
&self,
signing_key_fingerprint: &str,
) -> Result<(), AcdpError>
pub fn check_not_self_signed( &self, signing_key_fingerprint: &str, ) -> Result<(), AcdpError>
RFC-ACDP-0014 §5 step 2 — the revocation MUST NOT be signed by
the very key it revokes: such a statement proves only possession
of the (by hypothesis, attacker-held) key. Registries at ≥ 0.3.0
reject the publish with key_not_authorized; consumers MUST
treat one as unverified (at most a hint to seek a real
signal).
signing_key_fingerprint is the RFC-ACDP-0010 §6 fingerprint of
the resolved key that signed the revocation body (see
acdp_crypto::fingerprint).
Sourcepub fn revokes(&self, key_fingerprint: &str) -> bool
pub fn revokes(&self, key_fingerprint: &str) -> bool
True when this revocation applies to the given signing-key fingerprint (RFC-ACDP-0010 §6 encoding, exact match).
Sourcepub fn check_not_self_signed_lenient(
req: &PublishRequest,
signing_key_fingerprint: &str,
) -> Result<(), AcdpError>
pub fn check_not_self_signed_lenient( req: &PublishRequest, signing_key_fingerprint: &str, ) -> Result<(), AcdpError>
RFC-ACDP-0014 §5 step 2, decoupled from full §4 shape validation
(contrast Self::check_not_self_signed, which needs an already
shape-validated KeyRevocation). §10’s interim-form carve-out
is scoped explicitly to “§4 shape validation” — it says nothing
about §5, whose own MUST-reject text is gated on acdp_version
alone, not on which spelling of the context type was used. So a
registry on [0.3.0, 0.5.0) that must NOT §4-validate the
interim acdp:key-revocation form still MUST enforce this check
against it — this is the primitive that lets it do so without
pulling in the rest of §4.
Tolerant by design: a missing or non-string
metadata.revoked_key_fingerprint can’t be evaluated, so this
returns Ok(()) rather than rejecting on shape grounds — full §4
validation (standard type) or §5.11 signature verification is
what catches those cases instead. signing_key_fingerprint is
the RFC-ACDP-0010 §6 fingerprint of the resolved signing key.
Sourcepub fn check_not_self_signed_did_key_lenient(
req: &PublishRequest,
) -> Result<(), AcdpError>
pub fn check_not_self_signed_did_key_lenient( req: &PublishRequest, ) -> Result<(), AcdpError>
Self::check_not_self_signed_lenient’s did:key sub-case: the
signing key’s fingerprint is derivable from signature.key_id
alone, with no DID resolution — the same synchronous check
from_parts used to run unconditionally as a side effect of full
§4 parsing (before the interim form was carved out of that), now
exposed standalone so a caller (like PublishValidator) can run
it on a body it deliberately is NOT §4-shape-validating.
Tolerant by design: a non-did:key signer, an unresolvable
did:key key_id, or a fingerprint that fails to derive all leave
this a no-op — see Self::check_not_self_signed_lenient for
why that’s the right default.
Sourcepub fn cross_check_registry_binding(
&self,
serving_authority: &str,
capabilities_registry_did: &str,
) -> Result<(), AcdpError>
pub fn cross_check_registry_binding( &self, serving_authority: &str, capabilities_registry_did: &str, ) -> Result<(), AcdpError>
Registry-attestation binding (pure): publisher — the identity
this revocation was actually published under — MUST equal both
did:web:<serving_authority> (the authority the context was
actually fetched from, not whatever the body claims) AND the
serving registry’s advertised capabilities.registry_did. The
two halves have different citations: the registry_did half is
RFC-ACDP-0014 §6 step 2; the serving_authority half is not a
§6 step at all — it is the ACDP-wide registry_did↔authority
invariant of RFC-ACDP-0011 §7 step 3 / RFC-ACDP-0012 §9.3 step 3
(the two house-pattern siblings), applied here to key
revocations.
A RevocationTrustClass::RegistryAttested revocation imports
its authority entirely from who published it — §5 body
verification alone only proves the body is genuinely signed by
publisher’s current key, not that publisher is the specific
registry a caller actually talks to. Without this check a
consumer could apply a registry-attested revocation on the say-so
of any producer willing to name someone else as
revoked_key_controller; this pins publisher to the one
registry both the transport (serving_authority) and the
registry’s own self-description (capabilities_registry_did)
agree on.
Pure — no DID resolution or network I/O — so it stays exposable from the language bindings.
Trait Implementations§
Source§impl Clone for KeyRevocation
impl Clone for KeyRevocation
Source§impl Debug for KeyRevocation
impl Debug for KeyRevocation
Source§impl<'de> Deserialize<'de> for KeyRevocation
impl<'de> Deserialize<'de> for KeyRevocation
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for KeyRevocation
Source§impl PartialEq for KeyRevocation
impl PartialEq for KeyRevocation
Source§impl Serialize for KeyRevocation
impl Serialize for KeyRevocation
impl StructuralPartialEq for KeyRevocation
Auto Trait Implementations§
impl Freeze for KeyRevocation
impl RefUnwindSafe for KeyRevocation
impl Send for KeyRevocation
impl Sync for KeyRevocation
impl Unpin for KeyRevocation
impl UnsafeUnpin for KeyRevocation
impl UnwindSafe for KeyRevocation
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.