ssi_verification_methods_core/
lib.rs1use std::{borrow::Cow, collections::HashMap, sync::Arc};
2
3use iref::{Iri, IriBuf};
4use ssi_claims_core::{MessageSignatureError, ProofValidationError, SignatureError};
5use ssi_crypto::algorithm::SignatureAlgorithmType;
6use ssi_jwk::JWK;
7use static_iref::iri;
8
9mod controller;
10mod methods;
11mod reference;
12mod signature;
13mod verification;
14
15pub use controller::*;
16pub use methods::*;
17pub use reference::*;
18pub use signature::*;
19pub use verification::*;
20
21#[doc(hidden)]
22pub use ssi_core;
23
24pub const CONTROLLER_IRI: &Iri = iri!("https://w3id.org/security#controller");
27
28#[derive(Debug, Clone)]
30pub enum ExpectedType {
31 One(String),
32 Many(Vec<String>),
33}
34
35impl From<String> for ExpectedType {
36 fn from(value: String) -> Self {
37 Self::One(value)
38 }
39}
40
41pub trait VerificationMethod: Clone {
43 fn id(&self) -> &Iri;
45
46 fn controller(&self) -> Option<&Iri>; }
49
50#[derive(Debug, thiserror::Error)]
51pub enum VerificationMethodResolutionError {
52 #[error("unknown key")]
53 UnknownKey,
54
55 #[error("invalid key id `{0}`")]
57 InvalidKeyId(String),
58
59 #[error("id `{0}` is not referring to a verification method")]
61 NotAVerificationMethod(String),
62
63 #[error("unsupported key id `{0}`")]
65 UnsupportedKeyId(String),
66
67 #[error("missing verification method")]
68 MissingVerificationMethod,
69
70 #[error(transparent)]
71 InvalidVerificationMethod(#[from] InvalidVerificationMethod),
72
73 #[error("internal error: {0}")]
75 InternalError(String),
76}
77
78impl From<VerificationMethodResolutionError> for ProofValidationError {
79 fn from(value: VerificationMethodResolutionError) -> Self {
80 match value {
81 VerificationMethodResolutionError::MissingVerificationMethod => Self::MissingPublicKey,
82 e => Self::Other(e.to_string()),
83 }
84 }
85}
86
87impl From<VerificationMethodResolutionError> for SignatureError {
88 fn from(value: VerificationMethodResolutionError) -> Self {
89 match value {
90 VerificationMethodResolutionError::MissingVerificationMethod => Self::MissingSigner,
91 e => Self::other(e),
92 }
93 }
94}
95
96pub trait VerificationMethodSet: VerificationMethod {
97 type TypeSet: VerificationMethodTypeSet;
98
99 fn type_set() -> Self::TypeSet;
100}
101
102pub trait VerificationMethodTypeSet: 'static + Send + Sync {
103 fn pick(&self) -> Option<&str>;
104 fn contains(&self, ty: &str) -> bool;
105}
106
107impl VerificationMethodTypeSet for &'static str {
108 fn contains(&self, ty: &str) -> bool {
109 ty == *self
110 }
111
112 fn pick(&self) -> Option<&str> {
113 Some(self)
114 }
115}
116
117impl VerificationMethodTypeSet for &'static [&'static str] {
118 fn contains(&self, ty: &str) -> bool {
119 self.iter().any(|&t| t == ty)
120 }
121
122 fn pick(&self) -> Option<&str> {
123 self.first().copied()
124 }
125}
126
127#[derive(Default)]
128pub struct ResolutionOptions {
129 pub accept: Option<Box<dyn VerificationMethodTypeSet>>,
131}
132
133pub trait VerificationMethodResolver {
134 type Method: Clone;
136
137 #[allow(async_fn_in_trait)]
139 async fn resolve_verification_method_with(
140 &self,
141 issuer: Option<&Iri>,
142 method: Option<ReferenceOrOwnedRef<'_, Self::Method>>,
143 options: ResolutionOptions,
144 ) -> Result<Cow<Self::Method>, VerificationMethodResolutionError>;
145
146 #[allow(async_fn_in_trait)]
148 async fn resolve_verification_method(
149 &self,
150 issuer: Option<&Iri>,
151 method: Option<ReferenceOrOwnedRef<'_, Self::Method>>,
152 ) -> Result<Cow<Self::Method>, VerificationMethodResolutionError> {
153 self.resolve_verification_method_with(issuer, method, Default::default())
154 .await
155 }
156}
157
158impl<T: VerificationMethodResolver> VerificationMethodResolver for &T {
159 type Method = T::Method;
160
161 async fn resolve_verification_method_with(
162 &self,
163 issuer: Option<&Iri>,
164 method: Option<ReferenceOrOwnedRef<'_, T::Method>>,
165 options: ResolutionOptions,
166 ) -> Result<Cow<T::Method>, VerificationMethodResolutionError> {
167 T::resolve_verification_method_with(self, issuer, method, options).await
168 }
169}
170
171impl<M: VerificationMethod> VerificationMethodResolver for HashMap<IriBuf, M> {
172 type Method = M;
173
174 async fn resolve_verification_method_with(
175 &self,
176 _issuer: Option<&Iri>,
177 method: Option<ReferenceOrOwnedRef<'_, Self::Method>>,
178 _options: ResolutionOptions,
179 ) -> Result<Cow<Self::Method>, VerificationMethodResolutionError> {
180 match method {
181 Some(ReferenceOrOwnedRef::Owned(method)) => Ok(Cow::Owned(method.clone())),
182 Some(ReferenceOrOwnedRef::Reference(iri)) => match self.get(iri) {
183 Some(method) => Ok(Cow::Borrowed(method)),
184 None => Err(VerificationMethodResolutionError::UnknownKey),
185 },
186 None => Err(VerificationMethodResolutionError::MissingVerificationMethod),
187 }
188 }
189}
190
191pub trait SigningMethod<S, A: SignatureAlgorithmType>: VerificationMethod {
192 fn sign_bytes(
193 &self,
194 secret: &S,
195 algorithm: A::Instance,
196 bytes: &[u8],
197 ) -> Result<Vec<u8>, MessageSignatureError>;
198
199 fn sign_bytes_multi(
200 &self,
201 secret: &S,
202 algorithm: A::Instance,
203 messages: &[Vec<u8>],
204 ) -> Result<Vec<u8>, MessageSignatureError> {
205 match messages.split_first() {
206 Some((message, [])) => self.sign_bytes(secret, algorithm, message),
207 Some(_) => todo!(),
209 None => Err(MessageSignatureError::MissingMessage),
210 }
211 }
212}
213
214pub struct MethodWithSecret<M: VerificationMethod, S> {
215 pub method: M,
216 pub secret: Arc<S>,
217}
218
219impl<M: VerificationMethod, S> MethodWithSecret<M, S> {
220 pub fn new(method: M, secret: Arc<S>) -> Self {
221 Self { method, secret }
222 }
223}
224
225impl<A: SignatureAlgorithmType, M: SigningMethod<S, A>, S> MessageSigner<A>
226 for MethodWithSecret<M, S>
227{
228 async fn sign(
229 self,
230 algorithm: A::Instance,
231 message: &[u8],
232 ) -> Result<Vec<u8>, MessageSignatureError> {
233 self.method.sign_bytes(&self.secret, algorithm, message)
234 }
235
236 async fn sign_multi(
237 self,
238 algorithm: <A as SignatureAlgorithmType>::Instance,
239 messages: &[Vec<u8>],
240 ) -> Result<Vec<u8>, MessageSignatureError> {
241 self.method
242 .sign_bytes_multi(&self.secret, algorithm, messages)
243 }
244}
245
246pub trait TypedVerificationMethod: VerificationMethod {
247 fn expected_type() -> Option<ExpectedType>;
248
249 fn type_match(ty: &str) -> bool;
250
251 fn type_(&self) -> &str;
252}
253
254pub trait LinkedDataVerificationMethod {
255 fn quads(&self, quads: &mut Vec<rdf_types::Quad>) -> rdf_types::Object;
256}
257
258impl<T: LinkedDataVerificationMethod> LinkedDataVerificationMethod for &T {
259 fn quads(&self, quads: &mut Vec<rdf_types::Quad>) -> rdf_types::Object {
260 T::quads(*self, quads)
261 }
262}
263
264#[derive(Debug, thiserror::Error)]
265pub enum InvalidVerificationMethod {
266 #[error("invalid verification method IRI `{0}`")]
267 InvalidIri(String),
268
269 #[error("invalid verification method type IRI `{0}`")]
270 InvalidTypeIri(IriBuf),
271
272 #[error("invalid verification method type name `{0}`, expected `{1}`")]
273 InvalidTypeName(String, String),
274
275 #[error("missing verification method required property `{0}`")]
276 MissingProperty(String),
277
278 #[error("invalid verification method property `{0}`")]
279 InvalidProperty(String),
280
281 #[error("ambiguous public key")]
282 AmbiguousPublicKey,
283
284 #[error("unsupported method type `{0}`")]
285 UnsupportedMethodType(String),
286}
287
288impl InvalidVerificationMethod {
289 pub fn invalid_type_iri(iri: &Iri) -> Self {
290 Self::InvalidTypeIri(iri.to_owned())
291 }
292
293 pub fn invalid_type_name(name: &str, expected: &str) -> Self {
294 Self::InvalidTypeName(name.to_owned(), expected.to_owned())
295 }
296
297 pub fn missing_property(name: &str) -> Self {
298 Self::MissingProperty(name.to_owned())
299 }
300
301 pub fn invalid_property(name: &str) -> Self {
302 Self::InvalidProperty(name.to_owned())
303 }
304}
305
306impl From<InvalidVerificationMethod> for ProofValidationError {
307 fn from(_value: InvalidVerificationMethod) -> Self {
308 Self::InvalidKey
309 }
310}
311
312impl From<InvalidVerificationMethod> for SignatureError {
313 fn from(value: InvalidVerificationMethod) -> Self {
314 Self::other(value)
315 }
316}
317
318pub trait JwkVerificationMethod: VerificationMethod {
320 fn to_jwk(&self) -> Cow<JWK>;
321}
322
323pub trait MaybeJwkVerificationMethod: VerificationMethod {
325 fn try_to_jwk(&self) -> Option<Cow<JWK>>;
326}
327
328impl<M: JwkVerificationMethod> MaybeJwkVerificationMethod for M {
329 fn try_to_jwk(&self) -> Option<Cow<JWK>> {
330 Some(M::to_jwk(self))
331 }
332}