Skip to main content

co_identity/resolvers/
local.rs

1// SPDX-License-Identifier: AGPL-3.0-only
2// Copyright (C) 2026 1io BRANDGUARDIAN GmbH
3
4use crate::{
5	DidCommPrivateContext, DidCommPublicContext, Identity, IdentityBox, IdentityResolver, IdentityResolverError,
6	PrivateIdentity, PrivateIdentityBox, PrivateIdentityResolver,
7};
8use async_trait::async_trait;
9use co_primitives::Network;
10use std::collections::BTreeSet;
11
12/// A local identity without any actual signatures.
13#[derive(Debug, Clone)]
14pub struct LocalIdentity {
15	did: String,
16}
17impl LocalIdentity {
18	/// Device local identity. Owner of the local CO.
19	pub fn device() -> Self {
20		LocalIdentity { did: "did:local:device".to_owned() }
21	}
22
23	/// Device local identity.
24	///
25	/// # Note
26	/// This has no real usage. Use only for testing.
27	pub fn new(name: &str) -> Self {
28		LocalIdentity { did: format!("did:local:{name}") }
29	}
30}
31impl Identity for LocalIdentity {
32	fn identity(&self) -> &str {
33		self.did.as_str()
34	}
35
36	fn public_key(&self) -> Option<Vec<u8>> {
37		None
38	}
39
40	fn verify(&self, _signature: &[u8], _data: &[u8], _public_key: Option<&[u8]>) -> bool {
41		true
42	}
43
44	fn didcomm_public(&self) -> Option<DidCommPublicContext> {
45		None
46	}
47
48	fn networks(&self) -> BTreeSet<Network> {
49		Default::default()
50	}
51}
52impl PrivateIdentity for LocalIdentity {
53	fn sign(&self, data: &[u8]) -> Result<Vec<u8>, crate::SignError> {
54		Ok(data.to_vec())
55	}
56
57	fn didcomm_private(&self) -> Option<DidCommPrivateContext> {
58		None
59	}
60}
61
62#[derive(Debug, Clone, Default)]
63pub struct LocalIdentityResolver {}
64impl LocalIdentityResolver {
65	pub fn new() -> Self {
66		Self {}
67	}
68
69	fn into_local_identity(identity: &str) -> Result<LocalIdentity, IdentityResolverError> {
70		if identity.starts_with("did:local:") {
71			return Ok(LocalIdentity { did: identity.to_owned() });
72		}
73		Err(IdentityResolverError::NotFound)
74	}
75
76	pub fn private_identity(&self, identity: &str) -> Result<LocalIdentity, IdentityResolverError> {
77		Self::into_local_identity(identity)
78	}
79}
80#[async_trait]
81impl IdentityResolver for LocalIdentityResolver {
82	async fn resolve(&self, identity: &str) -> Result<IdentityBox, IdentityResolverError> {
83		Ok(IdentityBox::new(Self::into_local_identity(identity)?))
84	}
85}
86#[async_trait]
87impl PrivateIdentityResolver for LocalIdentityResolver {
88	async fn resolve_private(&self, identity: &str) -> Result<PrivateIdentityBox, IdentityResolverError> {
89		Ok(PrivateIdentityBox::new(Self::into_local_identity(identity)?))
90	}
91}