1use anyhow::Result;
4
5use super::{Config, Key, prelude::*};
6
7const FINGERPRINT_MIN_LEN: usize = 8;
12
13pub fn format_fingerprint<S: AsRef<str>>(fingerprint: S) -> String {
17 normalize_fingerprint(fingerprint)
18}
19
20pub fn normalize_fingerprint<S: AsRef<str>>(fingerprint: S) -> String {
30 let fp = fingerprint.as_ref().trim_start();
31
32 let fp = if fp.starts_with("0x") || fp.starts_with("0X") {
34 &fp[2..]
35 } else {
36 fp
37 };
38
39 let fp = fp.split('#').next().unwrap();
41
42 fp.trim_end().to_uppercase()
44}
45
46pub fn fingerprints_equal<S: AsRef<str>, T: AsRef<str>>(a: S, b: T) -> bool {
53 let a = normalize_fingerprint(a);
55 let b = normalize_fingerprint(b);
56
57 if a.len() < FINGERPRINT_MIN_LEN || b.len() < FINGERPRINT_MIN_LEN {
59 return false;
60 }
61
62 a.contains(&b)
63}
64
65pub fn keys_contain_fingerprint<S: AsRef<str>>(keys: &[Key], fingerprint: S) -> bool {
67 keys.iter()
68 .any(|key| fingerprints_equal(key.fingerprint(false), fingerprint.as_ref()))
69}
70
71pub fn has_private_key(config: &Config) -> Result<bool> {
73 Ok(!super::context(config)?.keys_private()?.is_empty())
74}
75
76#[cfg(test)]
77mod tests {
78 #[rustfmt::skip]
79 const FPS_NORMALIZE: &[(&str, &str)] = &[
80 ("E2D8DE4D35CE386F", "E2D8DE4D35CE386F"),
81 ("364119B9", "364119B9" ),
82 ("0xae78a4de7A738B54 ", "AE78A4DE7A738B54"),
83 ("0xB079912385023787 # username <user@example.com>", "B079912385023787"),
84 (" 0X47e3b6f9970b175f # some comment # something else ", "47E3B6F9970B175F"),
85 ];
86 #[rustfmt::skip]
87 const FPS_EQUAL: &[(&str, &str)] = &[
88 ("AAAAAAAA", "AAAAAAAA"),
90 ("e2d8de4d35CE386f", "E2D8DE4d35CE386f"),
92 ("0x364119B9", "0X364119B9"),
94 ("364119B9", "0x364119B9"),
95 ("364119B9 # comment 1", "364119B9 # comment 2"),
97 ("AE78A4DE7A738B54", "7A738B54"),
99 ("AE78A4DE7A738B54", "AE78A4DE"),
100 (" 0xAE78A4DE7A738B54 # username <user@example.com>", "a4de7a73"),
101 ];
102 #[rustfmt::skip]
103 const FPS_NOT_EQUAL: &[(&str, &str)] = &[
104 ("", ""),
106 ("AAAAAAA", "AAAAAAA"),
107 ("AAAAAAAA", "AAAAAAA"),
108 ("AAAAAAA", "AAAAAAAA"),
109 ("364119B9", "0364119B9"),
111 ("0xae78a4de7A738B54", "AE78A4DE7A738B540"),
112 ];
113
114 #[test]
115 fn test_normalize_fingerprint() {
116 for &(a, b) in FPS_NORMALIZE {
117 assert_eq!(
118 super::normalize_fingerprint(a),
119 b,
120 "{a:?} should normalize to {b:?}"
121 );
122 }
123 }
124
125 #[test]
126 fn test_fingerprints_equal() {
127 for &(a, b) in FPS_NORMALIZE {
128 assert!(
129 super::fingerprints_equal(a, b),
130 "{a:?} and {b:?} should be equal",
131 );
132 }
133 for &(a, b) in FPS_EQUAL {
134 assert!(
135 super::fingerprints_equal(a, b),
136 "{a:?} and {b:?} should be equal",
137 );
138 }
139 for &(a, b) in FPS_NOT_EQUAL {
140 assert!(
141 !super::fingerprints_equal(a, b),
142 "{a:?} and {b:?} should not be equal",
143 );
144 }
145 }
146}