diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-02-16 09:12:47 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2023-11-06 16:21:48 +0100 |
commit | bb8e1623e00a3e3b4e13e2adda11ff429770b0e2 (patch) | |
tree | 296b9c66db14bb4d04cfaa99425377ba84e76623 | |
parent | 967f9189aa65e4c8eca988280a52913b5936e9d8 (diff) |
openpgp: Make KeyHandle::partial_cmp transitive.
- Previously, KeyHandle::partial_cmp tried to sort aliasing handles
together. However, this made the function not transitive, which
is required by implementations of PartialOrd.
- Fix this by simply comparing the byte representations, and
computing aliasing in KeyHandle::aliases.
- Note: This makes PartialOrd (and PartialEq) total, but we still
don't implement Ord (and Eq) to prevent naive comparisons.
-rw-r--r-- | openpgp/src/keyhandle.rs | 48 |
1 files changed, 18 insertions, 30 deletions
diff --git a/openpgp/src/keyhandle.rs b/openpgp/src/keyhandle.rs index 5e6dc3d8..cf15bbaa 100644 --- a/openpgp/src/keyhandle.rs +++ b/openpgp/src/keyhandle.rs @@ -1,5 +1,4 @@ use std::convert::TryFrom; -use std::cmp; use std::cmp::Ordering; use std::borrow::Borrow; @@ -174,26 +173,7 @@ impl PartialOrd for KeyHandle { fn partial_cmp(&self, other: &KeyHandle) -> Option<Ordering> { let a = self.as_bytes(); let b = other.as_bytes(); - - let l = cmp::min(a.len(), b.len()); - - // Do a little endian comparison so that for v4 keys (where - // the KeyID is a suffix of the Fingerprint) equivalent KeyIDs - // and Fingerprints sort next to each other. - for (a, b) in a[a.len()-l..].iter().zip(b[b.len()-l..].iter()) { - let cmp = a.cmp(b); - if cmp != Ordering::Equal { - return Some(cmp); - } - } - - if a.len() == b.len() { - Some(Ordering::Equal) - } else { - // One (a KeyID) is the suffix of the other (a - // Fingerprint). - None - } + Some(a.cmp(b)) } } @@ -252,10 +232,6 @@ impl KeyHandle { /// fpr1 == keyid and fpr2 == keyid, but fpr1 != fpr2. /// ``` /// - /// In these cases (and only these cases) `KeyHandle`'s - /// `PartialOrd` implementation returns `None` to correctly - /// indicate that a comparison is not possible. - /// /// This definition of equality makes searching for a given /// `KeyHandle` using `PartialEq` awkward. This function fills /// that gap. It answers the question: given two `KeyHandles`, @@ -290,11 +266,23 @@ impl KeyHandle { pub fn aliases<H>(&self, other: H) -> bool where H: Borrow<KeyHandle> { - // This works, because the PartialOrd implementation only - // returns None if one value is a fingerprint and the other is - // a key id that matches the fingerprint's key id. - self.partial_cmp(other.borrow()).unwrap_or(Ordering::Equal) - == Ordering::Equal + let other = other.borrow(); + if self.partial_cmp(other) == Some(Ordering::Equal) { + true + } else { + match (self, other) { + (KeyHandle::Fingerprint(Fingerprint::V4(f)), + KeyHandle::KeyID(KeyID::V4(i))) + | (KeyHandle::KeyID(KeyID::V4(i)), + KeyHandle::Fingerprint(Fingerprint::V4(f))) => + { + // A v4 key ID are the 8 right-most octets of a v4 + // fingerprint. + &f[12..] == i + }, + _ => false, + } + } } /// Returns whether the KeyHandle is invalid. |