1use std::iter::once;
2
3use indexmap::IndexSet;
4use memberlist_proto::SecretKey;
5use parking_lot::RwLock;
6use triomphe::Arc;
7
8#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
10pub enum KeyringError {
11 #[error("secret key is not in the keyring")]
13 SecretKeyNotFound,
14 #[error("removing the primary key is not allowed")]
16 RemovePrimaryKey,
17}
18
19#[derive(Debug)]
20pub(super) struct KeyringInner {
21 pub(super) primary_key: SecretKey,
22 pub(super) keys: IndexSet<SecretKey>,
23}
24
25#[derive(Debug, Clone)]
32#[repr(transparent)]
33pub struct Keyring {
34 pub(super) inner: Arc<RwLock<KeyringInner>>,
35}
36
37impl Keyring {
38 #[inline]
47 pub fn new(primary_key: SecretKey) -> Self {
48 Self {
49 inner: Arc::new(RwLock::new(KeyringInner {
50 primary_key,
51 keys: IndexSet::new(),
52 })),
53 }
54 }
55
56 #[inline]
67 pub fn with_keys(
68 primary_key: SecretKey,
69 keys: impl Iterator<Item = impl Into<SecretKey>>,
70 ) -> Self {
71 if keys.size_hint().0 != 0 {
72 return Self {
73 inner: Arc::new(RwLock::new(KeyringInner {
74 primary_key,
75 keys: keys
76 .filter_map(|k| {
77 let k = k.into();
78 if k == primary_key { None } else { Some(k) }
79 })
80 .collect(),
81 })),
82 };
83 }
84
85 Self::new(primary_key)
86 }
87
88 #[inline]
91 pub fn primary_key(&self) -> SecretKey {
92 self.inner.read().primary_key
93 }
94
95 #[inline]
98 pub fn remove(&self, key: &[u8]) -> Result<(), KeyringError> {
99 let mut inner = self.inner.write();
100 if &inner.primary_key == key {
101 return Err(KeyringError::RemovePrimaryKey);
102 }
103 inner.keys.shift_remove(key);
104 Ok(())
105 }
106
107 #[inline]
114 pub fn insert(&self, key: SecretKey) {
115 self.inner.write().keys.insert(key);
116 }
117
118 #[inline]
121 pub fn use_key(&self, key_data: &[u8]) -> Result<(), KeyringError> {
122 let mut inner = self.inner.write();
123 if key_data == inner.primary_key.as_ref() {
124 return Ok(());
125 }
126
127 let Some(&key) = inner.keys.get(key_data) else {
129 return Err(KeyringError::SecretKeyNotFound);
130 };
131
132 let old_pk = inner.primary_key;
133 inner.keys.insert(old_pk);
134 inner.primary_key = key;
135 inner.keys.swap_remove(key_data);
136 Ok(())
137 }
138
139 #[inline]
141 pub fn keys(&self) -> impl Iterator<Item = SecretKey> + Send + 'static {
142 let inner = self.inner.read();
143
144 once(inner.primary_key).chain(inner.keys.clone())
147 }
148}
149
150#[cfg(feature = "serde")]
151const _: () = {
152 use memberlist_proto::SecretKeys;
153 use serde::{Deserialize, Serialize};
154
155 impl Serialize for Keyring {
156 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
157 where
158 S: serde::Serializer,
159 {
160 let keys = self.keys();
161 serializer.collect_seq(keys)
162 }
163 }
164
165 impl<'de> Deserialize<'de> for Keyring {
166 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
167 where
168 D: serde::Deserializer<'de>,
169 {
170 let keys = SecretKeys::deserialize(deserializer)?;
171 if keys.is_empty() {
172 return Err(serde::de::Error::custom(
173 "keyring must have at least one key",
174 ));
175 }
176
177 Ok(Keyring::with_keys(keys[0], keys.into_iter().skip(1)))
178 }
179 }
180};
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185
186 const TEST_KEYS: &[SecretKey] = &[
187 SecretKey::Aes128([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]),
188 SecretKey::Aes128([15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]),
189 SecretKey::Aes128([8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7]),
190 ];
191
192 #[test]
193 fn test_primary_only() {
194 let keyring = Keyring::new(TEST_KEYS[1]);
195 assert_eq!(keyring.keys().collect::<Vec<_>>().len(), 1);
196 }
197
198 #[test]
199 fn test_get_primary_key() {
200 let keyring = Keyring::with_keys(TEST_KEYS[1], TEST_KEYS.iter().copied());
201 assert_eq!(keyring.primary_key().as_ref(), TEST_KEYS[1].as_ref());
202 }
203
204 #[test]
205 fn test_insert_remove_use() {
206 let keyring = Keyring::new(TEST_KEYS[1]);
207
208 keyring.use_key(&TEST_KEYS[2]).unwrap_err();
210
211 keyring.insert(TEST_KEYS[2]);
213 assert_eq!(keyring.inner.read().keys.len() + 1, 2);
214 assert_eq!(keyring.keys().next().unwrap(), TEST_KEYS[1]);
215
216 keyring.use_key(&TEST_KEYS[2]).unwrap();
218 assert_eq!(keyring.keys().next().unwrap(), TEST_KEYS[2]);
219
220 let primary_key = keyring.primary_key();
221 assert_eq!(primary_key.as_ref(), TEST_KEYS[2].as_ref());
222
223 keyring.remove(&TEST_KEYS[2]).unwrap_err();
225
226 keyring.remove(&TEST_KEYS[1]).unwrap();
228 assert_eq!(keyring.inner.read().keys.len() + 1, 1);
229 }
230}