ssi_data_integrity_core/proof/de/
mod.rs1use crate::{
10 suite::bounds::{OptionsOf, SignatureOf, VerificationMethodOf},
11 CryptosuiteString, DeserializeCryptographicSuite, Proof, Type,
12};
13use serde::{
14 de::{DeserializeSeed, MapAccess},
15 Deserialize,
16};
17use ssi_core::{de::WithType, Lexical, OneOrMany};
18use std::{collections::BTreeMap, marker::PhantomData};
19
20mod field;
21pub use field::*;
22
23mod ref_or_value;
24pub use ref_or_value::*;
25
26mod utils;
27use utils::{FlatMapDeserializer, ReplayMap};
28
29mod configuration;
30
31fn datetime_to_utc_datetimestamp(
36 value: Option<Lexical<xsd_types::DateTime>>,
37) -> Option<Lexical<xsd_types::DateTimeStamp>> {
38 value.map(|lexical_dt| {
39 let (dt, mut representation) = lexical_dt.into_parts();
40
41 let dts = xsd_types::DateTimeStamp::new(
42 dt.date_time,
43 dt.offset.unwrap_or_else(|| {
44 if let Some(r) = &mut representation {
45 r.push('Z');
48 }
49
50 chrono::FixedOffset::east_opt(0).unwrap()
51 }),
52 );
53
54 Lexical::from_parts(dts, representation)
55 })
56}
57
58impl<'de, T: DeserializeCryptographicSuite<'de>> Proof<T> {
59 fn deserialize_with_type<S>(type_: Type, mut deserializer: S) -> Result<Self, S::Error>
60 where
61 S: serde::de::MapAccess<'de>,
62 {
63 let suite: T = type_
64 .try_into()
65 .map_err(|_| serde::de::Error::custom("unexpected cryptosuite"))?;
66
67 let mut context = None;
68 let mut created: Option<Lexical<xsd_types::DateTime>> = None;
69 let mut verification_method = None;
70 let mut proof_purpose = None;
71 let mut expires: Option<Lexical<xsd_types::DateTime>> = None;
72 let mut domains: Option<OneOrMany<String>> = None;
73 let mut challenge = None;
74 let mut nonce = None;
75
76 let mut other = Vec::new();
77
78 while let Some(key) = deserializer.next_key::<Field>()? {
79 match key {
80 Field::Context => context = Some(deserializer.next_value()?),
81 Field::Created => created = Some(deserializer.next_value()?),
82 Field::VerificationMethod => {
83 verification_method = Some({
84 deserializer
85 .next_value_seed(
86 WithType::<T, RefOrValue<VerificationMethodOf<T>>>::new(&suite),
87 )?
88 })
89 }
90 Field::ProofPurpose => proof_purpose = Some(deserializer.next_value()?),
91 Field::Expires => expires = Some(deserializer.next_value()?),
92 Field::Domains => domains = Some(deserializer.next_value()?),
93 Field::Challenge => challenge = Some(deserializer.next_value()?),
94 Field::Nonce => nonce = Some(deserializer.next_value()?),
95 Field::Other(key) => other.push(Some((key, deserializer.next_value()?))),
96 }
97 }
98
99 let options = WithType::<T, OptionsOf<T>>::new(&suite)
100 .deserialize(FlatMapDeserializer::new(&mut other))?
101 .0;
102
103 let signature = WithType::<T, SignatureOf<T>>::new(&suite)
104 .deserialize(FlatMapDeserializer::new(&mut other))?
105 .0;
106
107 Ok(Self {
108 context,
109 type_: suite,
110 created: datetime_to_utc_datetimestamp(created),
111 verification_method: verification_method
112 .map(|v| v.map(VerificationMethodOf::unwrap).into())
113 .ok_or_else(|| serde::de::Error::custom("missing `verificationMethod` property"))?,
114 proof_purpose: proof_purpose
115 .ok_or_else(|| serde::de::Error::custom("missing `proofPurpose` property"))?,
116 expires: datetime_to_utc_datetimestamp(expires),
117 domains: domains.map(|d| d.into_vec()).unwrap_or_default(),
118 challenge,
119 nonce,
120 options,
121 signature,
122 extra_properties: BTreeMap::deserialize(FlatMapDeserializer::new(&mut other))?,
123 })
124 }
125}
126
127impl<'de, T: DeserializeCryptographicSuite<'de>> serde::Deserialize<'de> for Proof<T> {
128 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
129 where
130 D: serde::Deserializer<'de>,
131 {
132 deserializer.deserialize_map(ProofVisitor(PhantomData))
133 }
134}
135
136struct ProofVisitor<T>(PhantomData<T>);
137
138impl<'de, T: DeserializeCryptographicSuite<'de>> serde::de::Visitor<'de> for ProofVisitor<T> {
139 type Value = Proof<T>;
140
141 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
142 write!(formatter, "Data-Integrity proof")
143 }
144
145 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
146 where
147 A: MapAccess<'de>,
148 {
149 let mut keep = Vec::new();
150 let mut cryptosuite = None;
151 let mut data_integrity_proof = false;
152
153 while let Some(key) = map.next_key::<TypeField>()? {
154 match key {
155 TypeField::Type => {
156 let name = map.next_value::<String>()?;
157
158 if name == "DataIntegrityProof" {
159 match cryptosuite.take() {
160 Some(c) => {
161 return Proof::<T>::deserialize_with_type(
162 Type::DataIntegrityProof(c),
163 ReplayMap::new(keep, map),
164 );
165 }
166 None => {
167 data_integrity_proof = true;
168 }
169 }
170 } else {
171 return Proof::<T>::deserialize_with_type(
172 Type::Other(name),
173 ReplayMap::new(keep, map),
174 );
175 }
176 }
177 TypeField::Cryptosuite => {
178 let name = map.next_value::<CryptosuiteString>()?;
179 if data_integrity_proof {
180 return Proof::<T>::deserialize_with_type(
181 Type::DataIntegrityProof(name),
182 ReplayMap::new(keep, map),
183 );
184 } else {
185 cryptosuite = Some(name)
186 }
187 }
188 TypeField::Other(key) => {
189 keep.push((key, map.next_value()?));
190 }
191 }
192 }
193
194 Err(serde::de::Error::custom("missing type"))
195 }
196}