Skip to main content

ssi_data_integrity_core/suite/
configuration.rs

1use std::marker::PhantomData;
2
3use ssi_claims_core::{ProofValidationError, SignatureError};
4use ssi_json_ld::syntax::Context;
5
6use crate::{CryptographicSuite, ProofConfiguration, ProofOptions};
7
8pub type InputVerificationMethod<S> = <<S as CryptographicSuite>::Configuration as ConfigurationAlgorithm<S>>::InputVerificationMethod;
9
10pub type InputSuiteOptions<S> =
11    <<S as CryptographicSuite>::Configuration as ConfigurationAlgorithm<S>>::InputSuiteOptions;
12
13pub type InputProofOptions<S> = ProofOptions<InputVerificationMethod<S>, InputSuiteOptions<S>>;
14
15pub type InputSignatureOptions<S> =
16    <<S as CryptographicSuite>::Configuration as ConfigurationAlgorithm<S>>::InputSignatureOptions;
17
18pub type InputVerificationOptions<S> =
19    <<S as CryptographicSuite>::Configuration as ConfigurationAlgorithm<S>>::InputVerificationOptions;
20
21pub type TransformationOptions<S> =
22    <<S as CryptographicSuite>::Configuration as ConfigurationAlgorithm<S>>::TransformationOptions;
23
24#[derive(Debug, thiserror::Error)]
25pub enum ConfigurationError {
26    #[error("missing verification method")]
27    MissingVerificationMethod,
28
29    #[error("missing option `{0}`")]
30    MissingOption(String),
31
32    #[error("invalid option `{0}`")]
33    InvalidOption(String),
34
35    #[error("{0}")]
36    Other(String),
37}
38
39impl From<std::convert::Infallible> for ConfigurationError {
40    fn from(_: std::convert::Infallible) -> Self {
41        unreachable!()
42    }
43}
44
45impl ConfigurationError {
46    pub fn invalid_option(e: impl ToString) -> Self {
47        Self::InvalidOption(e.to_string())
48    }
49
50    pub fn other(e: impl ToString) -> Self {
51        Self::Other(e.to_string())
52    }
53}
54
55impl From<ConfigurationError> for SignatureError {
56    fn from(value: ConfigurationError) -> Self {
57        Self::other(value)
58    }
59}
60
61impl From<ConfigurationError> for ProofValidationError {
62    fn from(value: ConfigurationError) -> Self {
63        Self::other(value)
64    }
65}
66
67pub trait ConfigurationAlgorithm<S: CryptographicSuite> {
68    /// Input type for the verification method.
69    type InputVerificationMethod;
70
71    /// Input suite-specific proof options.
72    ///
73    /// These options are stored in the `proof` object.
74    type InputSuiteOptions;
75
76    /// Input suite-specific signature options.
77    ///
78    /// These options do not appear in the `proof` object.
79    type InputSignatureOptions;
80
81    /// Input suite-specific verification options.
82    ///
83    /// These options do not appear in the `proof` object.
84    type InputVerificationOptions;
85
86    /// Document transformation options.
87    type TransformationOptions;
88
89    fn configure_signature(
90        suite: &S,
91        proof_options: ProofOptions<Self::InputVerificationMethod, Self::InputSuiteOptions>,
92        signature_options: InputSignatureOptions<S>,
93    ) -> Result<(ProofConfiguration<S>, Self::TransformationOptions), ConfigurationError>;
94
95    fn configure_verification(
96        suite: &S,
97        verification_options: &InputVerificationOptions<S>,
98    ) -> Result<Self::TransformationOptions, ConfigurationError>;
99}
100
101pub struct NoConfiguration;
102
103impl<S: CryptographicSuite> ConfigurationAlgorithm<S> for NoConfiguration {
104    type InputVerificationMethod = S::VerificationMethod;
105    type InputSuiteOptions = S::ProofOptions;
106
107    type InputSignatureOptions = ();
108
109    type InputVerificationOptions = ();
110
111    type TransformationOptions = ();
112
113    fn configure_signature(
114        suite: &S,
115        proof_options: ProofOptions<S::VerificationMethod, S::ProofOptions>,
116        _: InputSignatureOptions<S>,
117    ) -> Result<(ProofConfiguration<S>, Self::TransformationOptions), ConfigurationError> {
118        Ok((proof_options.into_configuration(suite.clone())?, ()))
119    }
120
121    fn configure_verification(
122        _suite: &S,
123        _verification_options: &InputVerificationOptions<S>,
124    ) -> Result<Self::TransformationOptions, ConfigurationError> {
125        Ok(())
126    }
127}
128
129pub struct AddProofContext<C>(PhantomData<C>);
130
131impl<C, S: CryptographicSuite + Default> ConfigurationAlgorithm<S> for AddProofContext<C>
132where
133    C: Default + Into<ssi_json_ld::syntax::Context>,
134{
135    type InputVerificationMethod = S::VerificationMethod;
136    type InputSuiteOptions = S::ProofOptions;
137    type InputSignatureOptions = ();
138    type InputVerificationOptions = ();
139    type TransformationOptions = ();
140
141    fn configure_signature(
142        suite: &S,
143        options: ProofOptions<S::VerificationMethod, S::ProofOptions>,
144        _: InputSignatureOptions<S>,
145    ) -> Result<(ProofConfiguration<S>, Self::TransformationOptions), ConfigurationError> {
146        let mut result = options.into_configuration(suite.clone())?;
147        result.context = match result.context {
148            None => Some(C::default().into()),
149            Some(c) => Some(Context::Many(
150                c.into_iter().chain(C::default().into()).collect(),
151            )),
152        };
153        Ok((result, ()))
154    }
155
156    fn configure_verification(
157        _suite: &S,
158        _verification_options: &InputVerificationOptions<S>,
159    ) -> Result<Self::TransformationOptions, ConfigurationError> {
160        Ok(())
161    }
162}