ssi_verification_methods_core/
lib.rs

1use 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
24/// IRI of the RDF property associated to the `controller` term found in a
25/// verification method.
26pub const CONTROLLER_IRI: &Iri = iri!("https://w3id.org/security#controller");
27
28/// Expected verification method type.
29#[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
41/// Verification method.
42pub trait VerificationMethod: Clone {
43    /// Identifier of the verification method.
44    fn id(&self) -> &Iri;
45
46    /// Returns the IRI of the verification method controller.
47    fn controller(&self) -> Option<&Iri>; // Should be an URI.
48}
49
50#[derive(Debug, thiserror::Error)]
51pub enum VerificationMethodResolutionError {
52    #[error("unknown key")]
53    UnknownKey,
54
55    /// Invalid key identifier.
56    #[error("invalid key id `{0}`")]
57    InvalidKeyId(String),
58
59    /// Not a verification method.
60    #[error("id `{0}` is not referring to a verification method")]
61    NotAVerificationMethod(String),
62
63    /// Unsupported key identifier.
64    #[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    /// Verifier internal error.
74    #[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    /// Accepted verification method types.
130    pub accept: Option<Box<dyn VerificationMethodTypeSet>>,
131}
132
133pub trait VerificationMethodResolver {
134    /// Verification method type.
135    type Method: Clone;
136
137    /// Resolve the verification method reference.
138    #[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    /// Resolve the verification method reference with the default options.
147    #[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(_) => Err(MessageSignatureError::TooManyMessages),
208            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
318/// Verification method that can be turned into a JSON Web Key.
319pub trait JwkVerificationMethod: VerificationMethod {
320    fn to_jwk(&self) -> Cow<JWK>;
321}
322
323/// Verification method that *may* be turned into a JSON Web Key.
324pub 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}