pgp/types/
key_id.rs

1/// Represents a Key ID.
2///
3/// This ID is always 8 bytes long, but calculated differently, depending on the key version.
4///
5/// <https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.4>
6#[derive(Clone, Copy, Hash, Eq, PartialEq, derive_more::Debug, derive_more::Display)]
7#[display("{}", hex::encode(_0))]
8#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
9pub struct KeyId(#[debug("{}", hex::encode(_0))] [u8; 8]);
10
11impl AsRef<[u8]> for KeyId {
12    fn as_ref(&self) -> &[u8] {
13        self.0.as_ref()
14    }
15}
16
17impl From<[u8; 8]> for KeyId {
18    fn from(value: [u8; 8]) -> Self {
19        Self::new(value)
20    }
21}
22
23impl KeyId {
24    /// The wild card ID, representing an "anonymous recipient".
25    pub const WILDCARD: KeyId = KeyId([0u8; 8]);
26
27    /// Creates a new fingerprint based on the provided bytes.
28    pub const fn new(id: [u8; 8]) -> Self {
29        Self(id)
30    }
31
32    /// True, if `self` is the "wild card" (or "anonymous recipient") Key ID of all zeros.
33    ///
34    /// See <https://www.rfc-editor.org/rfc/rfc9580.html#pkesk-notes>
35    pub fn is_wildcard(&self) -> bool {
36        self == &Self::WILDCARD
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn test_display() {
46        let keyid = KeyId::new([0x4C, 0x07, 0x3A, 0xE0, 0xC8, 0x44, 0x5C, 0x0C]);
47        assert_eq!("4c073ae0c8445c0c", format!("{keyid}"));
48    }
49
50    #[test]
51    fn test_wildcard() {
52        assert!(KeyId::WILDCARD.is_wildcard());
53        assert!(KeyId::from([0u8; 8]).is_wildcard());
54
55        assert!(!KeyId::from([1u8; 8]).is_wildcard());
56    }
57}