1use std::{
2 collections::{btree_map::Entry, BTreeMap},
3 sync::Arc,
4};
5
6use anyhow::Error;
7use futures::{stream::BoxStream, StreamExt};
8use libp2p::identity::{Keypair, PublicKey};
9use tokio::sync::Mutex;
10use zeroize::Zeroize;
11
12#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
13pub enum KeyType {
14 Ed25519,
15 Ecdsa,
16 Secp256k1,
17}
18
19#[derive(Clone)]
20pub struct Key {
21 key: Vec<u8>,
22}
23
24impl Drop for Key {
25 fn drop(&mut self) {
26 self.zeroize()
27 }
28}
29
30impl Zeroize for Key {
31 fn zeroize(&mut self) {
32 self.key.zeroize()
33 }
34}
35
36impl AsRef<[u8]> for Key {
37 fn as_ref(&self) -> &[u8] {
38 &self.key
39 }
40}
41
42impl From<Vec<u8>> for Key {
43 fn from(key: Vec<u8>) -> Self {
44 Self { key }
45 }
46}
47
48impl From<&[u8]> for Key {
49 fn from(key: &[u8]) -> Self {
50 key.to_vec().into()
51 }
52}
53
54#[derive(Clone)]
55pub struct Keystore {
56 storage: Arc<dyn KeyStorage>,
57}
58
59impl std::fmt::Debug for Keystore {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 f.debug_struct("Keystore").finish()
62 }
63}
64
65impl Keystore {
66 pub fn new(storage: Arc<dyn KeyStorage>) -> Self {
68 Self { storage }
69 }
70
71 pub fn in_memory() -> Self {
73 Self::new(Arc::new(MemoryKeyStorage::default()))
74 }
75
76 pub async fn import_key(
79 &self,
80 keypair: &Keypair,
81 name: Option<&str>,
82 ) -> Result<PublicKey, Error> {
83 let public_key = keypair.public();
84
85 let peer_id = public_key.to_peer_id().to_string();
86
87 let peer_id_str = peer_id.as_str();
88
89 let name = name.unwrap_or(peer_id_str);
90
91 let bytes = Key::from(keypair.to_protobuf_encoding()?);
92
93 self.storage.set(name, bytes.as_ref()).await?;
94
95 Ok(public_key)
96 }
97
98 pub async fn generate_ed25519(&self, name: Option<&str>) -> Result<PublicKey, Error> {
101 self.generate_key(name, KeyType::Ed25519).await
102 }
103
104 pub async fn generate_ecdsa(&self, name: Option<&str>) -> Result<PublicKey, Error> {
107 self.generate_key(name, KeyType::Ecdsa).await
108 }
109
110 pub async fn generate_secp256k1(&self, name: Option<&str>) -> Result<PublicKey, Error> {
113 self.generate_key(name, KeyType::Secp256k1).await
114 }
115
116 pub async fn generate_key(
119 &self,
120 name: Option<&str>,
121 key_type: KeyType,
122 ) -> Result<PublicKey, Error> {
123 let keypair = match key_type {
124 KeyType::Ed25519 => Keypair::generate_ed25519(),
125 KeyType::Ecdsa => Keypair::generate_ecdsa(),
126 KeyType::Secp256k1 => Keypair::generate_secp256k1(),
127 };
128 let public_key = keypair.public();
129
130 let peer_id = public_key.to_peer_id().to_string();
131
132 let peer_id_str = peer_id.as_str();
133
134 let bytes = Key::from(keypair.to_protobuf_encoding()?);
136
137 let name = name.unwrap_or(peer_id_str);
138
139 self.storage.set(name, bytes.as_ref()).await?;
140
141 Ok(public_key)
142 }
143
144 pub async fn get_keypair(&self, name: &str) -> Result<Keypair, Error> {
146 let key = self.storage.get(name).await?;
147 let keypair = Keypair::from_protobuf_encoding(key.as_ref())?;
148 Ok(keypair)
149 }
150
151 pub async fn rename(&self, name: &str, new_name: &str) -> Result<(), Error> {
153 self.storage.rename(name, new_name).await
154 }
155
156 pub async fn contains(&self, name: &str) -> Result<bool, Error> {
158 self.storage.contains(name).await
159 }
160}
161
162#[async_trait::async_trait]
163pub trait KeyStorage: Sync + Send + 'static {
164 async fn set(&self, name: &str, key: &[u8]) -> Result<(), Error>;
165 async fn get(&self, name: &str) -> Result<Key, Error>;
166 async fn contains(&self, name: &str) -> Result<bool, Error>;
167 async fn remove(&self, name: &str) -> Result<(), Error>;
168 async fn rename(&self, name: &str, new_name: &str) -> Result<(), Error>;
169 async fn list(&self) -> Result<BoxStream<'static, Key>, Error>;
170 async fn len(&self) -> Result<usize, Error> {
171 let amount = self.list().await?.count().await;
172 Ok(amount)
173 }
174}
175
176#[derive(Default)]
177pub struct MemoryKeyStorage {
178 inner: Mutex<BTreeMap<String, Key>>,
179}
180
181#[async_trait::async_trait]
182impl KeyStorage for MemoryKeyStorage {
183 async fn set(&self, name: &str, key: &[u8]) -> Result<(), Error> {
184 let mut inner = self.inner.lock().await;
185 match inner.entry(name.into()) {
186 Entry::Occupied(mut entry) => {
187 let key_entry = entry.get_mut();
188 *key_entry = key.into();
189 }
190 Entry::Vacant(entry) => {
191 entry.insert(key.into());
192 }
193 };
194
195 Ok(())
196 }
197 async fn get(&self, name: &str) -> Result<Key, Error> {
198 let inner = self.inner.lock().await;
199 inner
200 .get(name)
201 .cloned()
202 .ok_or(anyhow::anyhow!("Key doesnt exist"))
203 }
204 async fn remove(&self, name: &str) -> Result<(), Error> {
205 let mut inner = self.inner.lock().await;
206 inner
207 .remove(name)
208 .map(|_| ())
209 .ok_or(anyhow::anyhow!("Key doesnt exist"))
210 }
211
212 async fn contains(&self, name: &str) -> Result<bool, Error> {
213 let inner = self.inner.lock().await;
214 Ok(inner.contains_key(name))
215 }
216
217 async fn rename(&self, name: &str, new_name: &str) -> Result<(), Error> {
218 let mut inner = self.inner.lock().await;
219 if inner.contains_key(new_name) {
220 anyhow::bail!("{new_name} exist");
221 }
222
223 let key = inner
224 .remove(name)
225 .ok_or(anyhow::anyhow!("Key doesnt exist"))?;
226 inner.insert(new_name.into(), key);
227 Ok(())
228 }
229
230 async fn list(&self) -> Result<BoxStream<'static, Key>, Error> {
231 let inner = self.inner.lock().await.clone();
232 let stream = async_stream::stream! {
233 for (_, key) in inner {
234 yield key;
235 }
236 };
237
238 Ok(stream.boxed())
239 }
240}
241
242#[cfg(test)]
243mod test {
244 use crate::keystore::Keystore;
245
246 #[tokio::test]
247 async fn keystore_with_peerid() -> anyhow::Result<()> {
248 let keystore = Keystore::in_memory();
249 let pkey = keystore.generate_ed25519(None).await?;
250
251 let peer_id = pkey.to_peer_id().to_string();
252
253 let key = keystore.get_keypair(&peer_id).await?;
254
255 assert_eq!(key.public(), pkey);
256 Ok(())
257 }
258
259 #[tokio::test]
260 async fn keystore_with_name() -> anyhow::Result<()> {
261 let keystore = Keystore::in_memory();
262 let pkey = keystore.generate_ed25519(Some("primary")).await?;
263
264 let key = keystore.get_keypair("primary").await?;
265
266 assert_eq!(key.public(), pkey);
267 Ok(())
268 }
269
270 #[tokio::test]
271 async fn keystore_replace_existing() -> anyhow::Result<()> {
272 let keystore = Keystore::in_memory();
273 let public_key_1 = keystore.generate_ed25519(Some("primary")).await?;
274 let public_key_2 = keystore.generate_ed25519(Some("primary")).await?;
275 assert_ne!(public_key_1, public_key_2);
276 Ok(())
277 }
278
279 #[tokio::test]
280 async fn keystore_multiple_keys() -> anyhow::Result<()> {
281 let keystore = Keystore::in_memory();
282 let pkey1 = keystore.generate_ed25519(None).await?;
283 let pkey2 = keystore.generate_ed25519(None).await?;
284
285 let peer_id1 = pkey1.to_peer_id().to_string();
286 let peer_id2 = pkey2.to_peer_id().to_string();
287
288 let key1 = keystore.get_keypair(&peer_id1).await?;
289 let key2 = keystore.get_keypair(&peer_id2).await?;
290
291 assert_ne!(key1.public(), key2.public());
292 Ok(())
293 }
294
295 #[tokio::test]
296 async fn keystore_rename() -> anyhow::Result<()> {
297 let keystore = Keystore::in_memory();
298 let pkey = keystore.generate_ed25519(None).await?;
299
300 let peer_id = pkey.to_peer_id().to_string();
301
302 keystore.rename(&peer_id, "primary").await?;
303
304 let result = keystore.get_keypair(&peer_id).await;
305 assert!(result.is_err());
306
307 let key = keystore.get_keypair("primary").await?;
308
309 assert_eq!(key.public(), pkey);
310
311 Ok(())
312 }
313}