1use core::fmt;
5use std::sync::{Arc, PoisonError, RwLock};
6
7use super::{Identifier, Identity, IdentityError, IdentityKind};
8use crate::did::{DidMethod, DidUrl};
9use crate::jose::{Jwk, JwsAlgorithm, KeyType, SignError, Signer};
10use crate::keys::{KeyId, KeySigner, KeySpec, KeyStore, KeyStoreError};
11use crate::resolver::DidProducer;
12
13pub struct KeyStoreIdentity {
60 store: Arc<dyn KeyStore>,
61 producers: Vec<Arc<dyn DidProducer<Params = ()>>>,
62 generate_missing: bool,
63 bindings: RwLock<Vec<Binding>>,
64}
65
66#[derive(Clone)]
68struct Binding {
69 kind: IdentityKind,
70 signer: KeySigner<Arc<dyn KeyStore>>,
71 identifier: Identifier,
72 kid: Option<String>,
73}
74
75impl KeyStoreIdentity {
76 pub fn new(store: Arc<dyn KeyStore>) -> Self {
78 Self {
79 store,
80 producers: Vec::new(),
81 generate_missing: false,
82 bindings: RwLock::new(Vec::new()),
83 }
84 }
85
86 #[must_use]
93 pub fn with_producer(mut self, producer: impl DidProducer<Params = ()> + 'static) -> Self {
94 self.producers
95 .retain(|registered| registered.method() != producer.method());
96 self.producers.push(Arc::new(producer));
97 self
98 }
99
100 #[must_use]
104 pub fn generate_missing(mut self, enabled: bool) -> Self {
105 self.generate_missing = enabled;
106 self
107 }
108
109 pub async fn bind(
121 &self,
122 kind: IdentityKind,
123 alg: JwsAlgorithm,
124 key: KeyId,
125 ) -> Result<Identifier, IdentityError> {
126 let binding = self.derive(kind, alg, key).await?;
127 let identifier = binding.identifier.clone();
128 self.insert(binding, true);
129 Ok(identifier)
130 }
131
132 pub async fn bind_did_url(
145 &self,
146 kind: IdentityKind,
147 alg: JwsAlgorithm,
148 key: KeyId,
149 url: DidUrl,
150 ) -> Result<Identifier, IdentityError> {
151 match &kind {
152 IdentityKind::Did(method) if method.matches(url.did()) => {}
153 _ => return Err(IdentityError::UnsupportedKind(kind)),
154 }
155 let signer = self.signer_for(alg, key).await?;
156 let identifier = Identifier::Did(url.did().clone());
157 self.insert(
158 Binding {
159 kind,
160 signer,
161 identifier: identifier.clone(),
162 kid: Some(url.to_string()),
163 },
164 true,
165 );
166 Ok(identifier)
167 }
168
169 pub fn bindings(&self) -> Vec<(IdentityKind, JwsAlgorithm, KeyId)> {
172 self.read()
173 .iter()
174 .map(|binding| {
175 (
176 binding.kind.clone(),
177 binding.signer.alg(),
178 binding.signer.key_id().clone(),
179 )
180 })
181 .collect()
182 }
183
184 async fn signer_for(
187 &self,
188 alg: JwsAlgorithm,
189 key: KeyId,
190 ) -> Result<KeySigner<Arc<dyn KeyStore>>, IdentityError> {
191 KeySigner::new(Arc::clone(&self.store), key, alg)
192 .await
193 .map_err(|error| match error {
194 KeyStoreError::UnsupportedAlgorithm(alg) => {
195 IdentityError::UnsupportedAlgorithm(alg)
196 }
197 error => IdentityError::KeyStore(error),
198 })
199 }
200
201 #[expect(
203 clippy::similar_names,
204 reason = "`kind` and `kid` are the terms of the API"
205 )]
206 async fn derive(
207 &self,
208 kind: IdentityKind,
209 alg: JwsAlgorithm,
210 key: KeyId,
211 ) -> Result<Binding, IdentityError> {
212 let producer = match &kind {
213 IdentityKind::Did(method) => Some(
214 self.producer(method)
215 .ok_or_else(|| IdentityError::UnsupportedKind(kind.clone()))?,
216 ),
217 IdentityKind::JwkThumbprint => None,
218 };
219 let signer = self.signer_for(alg, key).await?;
220 let public = signer.public_jwk().public();
221 let (identifier, kid) = match (&kind, producer) {
222 (IdentityKind::Did(method), Some(producer)) => {
223 let document = producer.produce(&[public], ()).await?;
224 if !method.matches(&document.id) {
225 return Err(IdentityError::UnsupportedKind(kind));
226 }
227 let kid = document
228 .methods(None)
229 .next()
230 .map(|method| method.id.to_string())
231 .ok_or_else(|| IdentityError::NoVerificationMethod(document.id.clone()))?;
232 (Identifier::Did(document.id), Some(kid))
233 }
234 _ => (Identifier::JwkThumbprint(public.thumbprint_sha256()?), None),
235 };
236 Ok(Binding {
237 kind,
238 signer,
239 identifier,
240 kid,
241 })
242 }
243
244 fn producer(&self, method: &DidMethod) -> Option<&Arc<dyn DidProducer<Params = ()>>> {
246 self.producers
247 .iter()
248 .find(|producer| producer.method() == method.name())
249 }
250
251 async fn binding(
253 &self,
254 kind: &IdentityKind,
255 alg: JwsAlgorithm,
256 ) -> Result<Binding, IdentityError> {
257 if let Some(binding) = self.find(kind, alg) {
258 return Ok(binding);
259 }
260 if !self.generate_missing {
261 return Err(if self.read().iter().any(|binding| binding.kind == *kind) {
262 IdentityError::UnsupportedAlgorithm(alg)
263 } else {
264 IdentityError::UnsupportedKind(kind.clone())
265 });
266 }
267 if let IdentityKind::Did(method) = kind
268 && self.producer(method).is_none()
269 {
270 return Err(IdentityError::UnsupportedKind(kind.clone()));
271 }
272 let capabilities = self.store.capabilities();
273 let Some(key_type) = key_type_for(alg).filter(|_| capabilities.supports(alg)) else {
274 return Err(IdentityError::UnsupportedAlgorithm(alg));
275 };
276 if !capabilities.can_generate {
277 return Err(KeyStoreError::Unsupported("generate").into());
278 }
279 let key = self.store.generate(KeySpec::new(key_type, alg)).await?;
280 let binding = match self.derive(kind.clone(), alg, key.clone()).await {
281 Ok(binding) => binding,
282 Err(error) => {
283 self.discard(&key).await;
284 return Err(error);
285 }
286 };
287 let kept = self.insert(binding, false);
288 if kept.signer.key_id() != &key {
290 self.discard(&key).await;
291 }
292 Ok(kept)
293 }
294
295 async fn discard(&self, key: &KeyId) {
297 if self.store.capabilities().can_delete {
298 let _ = self.store.delete(key).await;
300 }
301 }
302
303 fn find(&self, kind: &IdentityKind, alg: JwsAlgorithm) -> Option<Binding> {
304 self.read()
305 .iter()
306 .find(|binding| binding.kind == *kind && binding.signer.alg() == alg)
307 .cloned()
308 }
309
310 fn insert(&self, binding: Binding, replace: bool) -> Binding {
313 let mut bindings = self
314 .bindings
315 .write()
316 .unwrap_or_else(PoisonError::into_inner);
317 let existing = bindings
318 .iter_mut()
319 .find(|bound| bound.kind == binding.kind && bound.signer.alg() == binding.signer.alg());
320 match existing {
321 Some(bound) if replace => {
322 *bound = binding.clone();
323 binding
324 }
325 Some(bound) => bound.clone(),
326 None => {
327 bindings.push(binding.clone());
328 binding
329 }
330 }
331 }
332
333 fn read(&self) -> std::sync::RwLockReadGuard<'_, Vec<Binding>> {
334 self.bindings.read().unwrap_or_else(PoisonError::into_inner)
335 }
336}
337
338fn key_type_for(alg: JwsAlgorithm) -> Option<KeyType> {
341 match alg {
342 JwsAlgorithm::EdDSA => Some(KeyType::Ed25519),
343 JwsAlgorithm::ES256 => Some(KeyType::P256),
344 JwsAlgorithm::ES256K => Some(KeyType::Secp256k1),
345 JwsAlgorithm::RS256 | JwsAlgorithm::PS256 => Some(KeyType::Rsa2048),
346 JwsAlgorithm::ES384 => None,
347 }
348}
349
350impl fmt::Debug for KeyStoreIdentity {
351 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352 let producers: Vec<&str> = self
353 .producers
354 .iter()
355 .map(|producer| producer.method())
356 .collect();
357 f.debug_struct("KeyStoreIdentity")
358 .field("producers", &producers)
359 .field("generate_missing", &self.generate_missing)
360 .field("bindings", &self.bindings())
361 .finish_non_exhaustive()
362 }
363}
364
365#[async_trait::async_trait]
366impl Identity for KeyStoreIdentity {
367 fn capabilities(&self) -> Vec<(IdentityKind, JwsAlgorithm)> {
372 let mut pairs: Vec<(IdentityKind, JwsAlgorithm)> = self
373 .read()
374 .iter()
375 .map(|binding| (binding.kind.clone(), binding.signer.alg()))
376 .collect();
377 let capabilities = self.store.capabilities();
378 if self.generate_missing && capabilities.can_generate {
379 let kinds = self
380 .producers
381 .iter()
382 .filter_map(|producer| DidMethod::new(producer.method()).ok())
383 .map(IdentityKind::Did)
384 .chain([IdentityKind::JwkThumbprint]);
385 for kind in kinds {
386 for &alg in &capabilities.algorithms {
387 if key_type_for(alg).is_some() && !pairs.contains(&(kind.clone(), alg)) {
388 pairs.push((kind.clone(), alg));
389 }
390 }
391 }
392 }
393 pairs
394 }
395
396 async fn identifier(
397 &self,
398 kind: &IdentityKind,
399 alg: JwsAlgorithm,
400 ) -> Result<Identifier, IdentityError> {
401 Ok(self.binding(kind, alg).await?.identifier)
402 }
403
404 async fn public_jwk(
405 &self,
406 kind: &IdentityKind,
407 alg: JwsAlgorithm,
408 ) -> Result<Jwk, IdentityError> {
409 Ok(self.binding(kind, alg).await?.signer.public_jwk().public())
410 }
411
412 async fn signer(
413 &self,
414 kind: &IdentityKind,
415 alg: JwsAlgorithm,
416 ) -> Result<Box<dyn Signer + '_>, IdentityError> {
417 let binding = self.binding(kind, alg).await?;
418 Ok(Box::new(BoundSigner {
419 signer: binding.signer,
420 kid: binding.kid,
421 }))
422 }
423}
424
425struct BoundSigner {
428 signer: KeySigner<Arc<dyn KeyStore>>,
429 kid: Option<String>,
430}
431
432#[async_trait::async_trait]
433impl Signer for BoundSigner {
434 fn alg(&self) -> JwsAlgorithm {
435 self.signer.alg()
436 }
437
438 fn kid(&self) -> Option<&str> {
439 self.kid.as_deref()
440 }
441
442 async fn sign(&self, signing_input: &[u8]) -> Result<Vec<u8>, SignError> {
443 self.signer.sign(signing_input).await
444 }
445}