ssi_data_integrity_core/proof/configuration/
mod.rs1use iref::Iri;
2use serde::Serialize;
3use ssi_core::Lexical;
4use ssi_verification_methods::{ProofPurpose, ReferenceOrOwned};
5use static_iref::iri;
6use std::collections::BTreeMap;
7
8use crate::{CryptographicSuite, Proof, ProofOptions, SerializeCryptographicSuite};
9
10pub const DC_CREATED_IRI: &Iri = iri!("http://purl.org/dc/terms/created");
11
12pub const XSD_DATETIME_IRI: &Iri = iri!("http://www.w3.org/2001/XMLSchema#dateTime");
13
14mod expansion;
15mod reference;
16
17pub use expansion::*;
18pub use reference::*;
19
20#[derive(Debug, Clone, Serialize)]
24#[serde(rename_all = "camelCase", bound = "S: SerializeCryptographicSuite")]
25pub struct ProofConfiguration<S: CryptographicSuite> {
26 #[serde(rename = "@context", default, skip_serializing_if = "Option::is_none")]
27 pub context: Option<ssi_json_ld::syntax::Context>,
28
29 #[serde(flatten, serialize_with = "S::serialize_type")]
31 pub type_: S,
32
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub created: Option<Lexical<xsd_types::DateTimeStamp>>,
36
37 #[serde(serialize_with = "S::serialize_verification_method_ref")]
39 pub verification_method: ReferenceOrOwned<S::VerificationMethod>,
40
41 pub proof_purpose: ProofPurpose,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
46 pub expires: Option<Lexical<xsd_types::DateTimeStamp>>,
47
48 #[allow(rustdoc::bare_urls)]
49 #[serde(
62 with = "crate::value_or_array",
63 skip_serializing_if = "Vec::is_empty",
64 rename = "domain"
65 )]
66 pub domains: Vec<String>,
67
68 #[serde(skip_serializing_if = "Option::is_none")]
74 pub challenge: Option<String>,
75
76 #[serde(skip_serializing_if = "Option::is_none")]
81 pub nonce: Option<String>,
82
83 #[serde(flatten, serialize_with = "S::serialize_proof_options")]
88 pub options: S::ProofOptions,
89
90 #[serde(flatten)]
92 pub extra_properties: BTreeMap<String, json_syntax::Value>,
93}
94
95impl<S: CryptographicSuite> ProofConfiguration<S> {
96 pub fn new(
97 type_: S,
98 created: Lexical<xsd_types::DateTimeStamp>,
99 verification_method: ReferenceOrOwned<S::VerificationMethod>,
100 proof_purpose: ProofPurpose,
101 options: S::ProofOptions,
102 ) -> Self {
103 Self {
104 context: None,
105 type_,
106 created: Some(created),
107 verification_method,
108 proof_purpose,
109 expires: None,
110 domains: Vec::new(),
111 challenge: None,
112 nonce: None,
113 options,
114 extra_properties: BTreeMap::new(),
115 }
116 }
117
118 pub fn from_method_and_options(
119 type_: S,
120 verification_method: ReferenceOrOwned<S::VerificationMethod>,
121 options: S::ProofOptions,
122 ) -> Self {
123 Self {
124 context: None,
125 type_,
126 created: Some(xsd_types::DateTimeStamp::now_ms().into()),
127 verification_method,
128 proof_purpose: ProofPurpose::default(),
129 expires: None,
130 domains: Vec::new(),
131 challenge: None,
132 nonce: None,
133 options,
134 extra_properties: BTreeMap::new(),
135 }
136 }
137
138 pub fn from_method(
139 type_: S,
140 verification_method: ReferenceOrOwned<S::VerificationMethod>,
141 ) -> Self
142 where
143 S::ProofOptions: Default,
144 {
145 Self::from_method_and_options(type_, verification_method, Default::default())
146 }
147
148 pub fn into_suite_and_options(
149 self,
150 ) -> (S, ProofOptions<S::VerificationMethod, S::ProofOptions>) {
151 (
152 self.type_,
153 ProofOptions {
154 context: self.context,
155 created: self.created,
156 verification_method: Some(self.verification_method),
157 proof_purpose: self.proof_purpose,
158 expires: self.expires,
159 domains: self.domains,
160 challenge: self.challenge,
161 nonce: self.nonce,
162 options: self.options,
163 extra_properties: self.extra_properties,
164 },
165 )
166 }
167
168 pub fn into_options(self) -> ProofOptions<S::VerificationMethod, S::ProofOptions> {
169 ProofOptions {
170 context: self.context,
171 created: self.created,
172 verification_method: Some(self.verification_method),
173 proof_purpose: self.proof_purpose,
174 expires: self.expires,
175 domains: self.domains,
176 challenge: self.challenge,
177 nonce: self.nonce,
178 options: self.options,
179 extra_properties: self.extra_properties,
180 }
181 }
182
183 pub fn into_proof(self, signature: S::Signature) -> Proof<S> {
184 Proof {
185 context: self.context,
186 type_: self.type_,
187 created: self.created,
188 verification_method: self.verification_method,
189 proof_purpose: self.proof_purpose,
190 expires: self.expires,
191 domains: self.domains,
192 challenge: self.challenge,
193 nonce: self.nonce,
194 options: self.options,
195 signature,
196 extra_properties: self.extra_properties,
197 }
198 }
199
200 pub fn map<T: CryptographicSuite>(
201 self,
202 map_type: impl FnOnce(S) -> T,
203 map_verification_method: impl FnOnce(S::VerificationMethod) -> T::VerificationMethod,
204 map_options: impl FnOnce(S::ProofOptions) -> T::ProofOptions,
205 ) -> ProofConfiguration<T> {
206 ProofConfiguration {
207 context: self.context,
208 type_: map_type(self.type_),
209 created: self.created,
210 verification_method: self.verification_method.map(map_verification_method),
211 proof_purpose: self.proof_purpose,
212 expires: self.expires,
213 domains: self.domains,
214 challenge: self.challenge,
215 nonce: self.nonce,
216 options: map_options(self.options),
217 extra_properties: self.extra_properties,
218 }
219 }
220
221 pub fn borrowed(&'_ self) -> ProofConfigurationRef<'_, S> {
222 ProofConfigurationRef {
223 context: self.context.as_ref(),
224 type_: &self.type_,
225 created: self.created.as_ref(),
226 verification_method: self.verification_method.borrowed(),
227 proof_purpose: self.proof_purpose,
228 expires: self.expires.as_ref(),
229 domains: &self.domains,
230 challenge: self.challenge.as_deref(),
231 nonce: self.nonce.as_deref(),
232 options: &self.options,
233 extra_properties: &self.extra_properties,
234 }
235 }
236}
237
238#[derive(Debug, thiserror::Error)]
239pub enum ProofConfigurationCastError<M, O> {
240 #[error("invalid verification method")]
241 VerificationMethod(M),
242
243 #[error("invalid options")]
244 Options(O),
245}