identity_kit/keys/
in_memory.rs1use core::fmt;
4use std::sync::{Mutex, PoisonError, RwLock};
5
6use indexmap::IndexMap;
7
8use super::local::{self, Entry, SeededRandom};
9use super::{KeyId, KeySpec, KeyStore, KeyStoreCapabilities, KeyStoreError};
10use crate::jose::{Jwk, JwsAlgorithm};
11
12pub struct InMemoryKeyStore {
45 keys: RwLock<IndexMap<KeyId, Entry>>,
46 seeded: Option<Mutex<SeededRandom>>,
47}
48
49impl Default for InMemoryKeyStore {
50 fn default() -> Self {
51 Self::new()
52 }
53}
54
55impl InMemoryKeyStore {
56 pub fn new() -> Self {
58 Self {
59 keys: RwLock::new(IndexMap::new()),
60 seeded: None,
61 }
62 }
63
64 pub fn with_seed(seed: [u8; 32]) -> Self {
68 Self {
69 keys: RwLock::new(IndexMap::new()),
70 seeded: Some(Mutex::new(SeededRandom::new(seed))),
71 }
72 }
73
74 pub fn key_ids(&self) -> Vec<KeyId> {
76 self.keys
77 .read()
78 .unwrap_or_else(PoisonError::into_inner)
79 .keys()
80 .cloned()
81 .collect()
82 }
83
84 pub fn is_seeded(&self) -> bool {
86 self.seeded.is_some()
87 }
88
89 fn random(&self, buf: &mut [u8]) -> Result<(), KeyStoreError> {
90 match &self.seeded {
91 Some(seeded) => {
92 seeded
93 .lock()
94 .unwrap_or_else(PoisonError::into_inner)
95 .fill(buf);
96 Ok(())
97 }
98 None => local::os_random(buf),
99 }
100 }
101}
102
103impl fmt::Debug for InMemoryKeyStore {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 f.debug_struct("InMemoryKeyStore")
106 .field("keys", &self.key_ids())
107 .field("seeded", &self.is_seeded())
108 .finish()
109 }
110}
111
112#[async_trait::async_trait]
113impl KeyStore for InMemoryKeyStore {
114 fn capabilities(&self) -> KeyStoreCapabilities {
115 KeyStoreCapabilities::new(local::ALGORITHMS.iter().copied())
116 .with_generate()
117 .with_delete()
118 }
119
120 async fn public_jwk(&self, key: &KeyId) -> Result<Jwk, KeyStoreError> {
121 self.keys
122 .read()
123 .unwrap_or_else(PoisonError::into_inner)
124 .get(key)
125 .map(Entry::public_jwk)
126 .ok_or_else(|| KeyStoreError::NotFound(key.clone()))
127 }
128
129 async fn sign(
130 &self,
131 key: &KeyId,
132 alg: JwsAlgorithm,
133 data: &[u8],
134 ) -> Result<Vec<u8>, KeyStoreError> {
135 self.keys
136 .read()
137 .unwrap_or_else(PoisonError::into_inner)
138 .get(key)
139 .ok_or_else(|| KeyStoreError::NotFound(key.clone()))?
140 .sign(key, alg, data)
141 }
142
143 async fn exists(&self, key: &KeyId) -> Result<bool, KeyStoreError> {
144 Ok(self
145 .keys
146 .read()
147 .unwrap_or_else(PoisonError::into_inner)
148 .contains_key(key))
149 }
150
151 async fn generate(&self, spec: KeySpec) -> Result<KeyId, KeyStoreError> {
152 let (id, key) = local::generate(&spec, &mut |buf| self.random(buf))?;
153 let mut keys = self.keys.write().unwrap_or_else(PoisonError::into_inner);
154 if keys.contains_key(&id) {
155 return Err(KeyStoreError::AlreadyExists(id));
156 }
157 keys.insert(id.clone(), Entry::new(&id, key, spec.alg));
158 Ok(id)
159 }
160
161 async fn delete(&self, key: &KeyId) -> Result<(), KeyStoreError> {
162 self.keys
163 .write()
164 .unwrap_or_else(PoisonError::into_inner)
165 .shift_remove(key)
166 .map(drop)
167 .ok_or_else(|| KeyStoreError::NotFound(key.clone()))
168 }
169}