co_identity/types/didcomm/
message.rs1use crate::{
5 library::didcomm_receive::didcomm_receive, DidCommContext, DidCommHeader, Identity, IdentityResolver,
6 PrivateIdentity, PrivateIdentityResolver, ReceiveError,
7};
8use anyhow::anyhow;
9use co_primitives::{from_json_string, Did};
10use didcomm_rs::{Jwe, Jws, MessageType};
11use serde::{de::DeserializeOwned, Deserialize, Serialize};
12use serde_json::value::RawValue;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum Message {
19 PlainJson { header: DidCommHeader, body: String },
24
25 SignedJson { sender: Did, header: DidCommHeader, body: String },
32
33 AnonCryptJson { header: DidCommHeader, body: String },
40
41 AuthCryptJson { sender: Did, header: DidCommHeader, body: String },
54}
55impl Message {
56 pub async fn receive<I, P>(sender_resolver: I, recipent_resolver: P, data: &[u8]) -> Result<Message, ReceiveError>
58 where
59 I: IdentityResolver + Send + Sync + 'static,
60 P: PrivateIdentityResolver + Send + Sync + 'static,
61 {
62 let message = std::str::from_utf8(data).map_err(|e| ReceiveError::UnknownFormat(e.into()))?;
63 let message_type = get_message_type(message).map_err(ReceiveError::UnknownFormat)?;
64 if message_type == MessageType::DidCommJwe {
65 let jwe: Jwe = serde_json::from_str(message).map_err(|e| ReceiveError::UnknownFormat(e.into()))?;
66
67 let sender_identity = if let Some(sender_kid) = &jwe.get_skid() {
69 Some(
70 sender_resolver
71 .resolve(sender_kid)
72 .await
73 .map_err(|e| ReceiveError::BadDid(sender_kid.to_owned(), e.into()))?,
74 )
75 } else {
76 None
77 };
78
79 let recipents = jwe
81 .recipients
82 .unwrap_or_else(|| jwe.recipient.map(|item| vec![item]).unwrap_or_default());
83 let recipent_resolver_ref = &recipent_resolver;
84
85 for recipent in &recipents {
87 let recipent_did = match &recipent.header.kid {
88 Some(kid) => kid,
89 None => continue,
90 };
91 let recipent_identity = match recipent_resolver_ref.resolve_private(recipent_did).await {
92 Ok(i) => i,
93 Err(_) => continue,
94 };
95 let recipent_didcomm_context = match recipent_identity.didcomm_private() {
96 Some(i) => i,
97 None => continue,
98 };
99 let (header, body) = recipent_didcomm_context.receive(&sender_resolver, message).await?;
100
101 if let Some(from) = &header.from {
105 if let Some(sender_identity) = sender_identity {
106 if from == sender_identity.identity() {
107 return Ok(Message::AuthCryptJson {
108 sender: sender_identity.identity().to_owned(),
109 header,
110 body,
111 });
112 }
113 }
114 }
115 return Ok(Message::AnonCryptJson { header, body });
116 }
117 return Err(ReceiveError::NoRecipent);
118 }
119 if message_type == MessageType::DidCommJws {
120 let (header, body) = didcomm_receive(None, &sender_resolver, message).await?;
121
122 let sender = verify_signing_identity(&sender_resolver, &header, message).await?;
124
125 return Ok(Message::SignedJson { sender, header, body });
127 }
128 if message_type == MessageType::DidCommRaw {
129 let plain_message: DidCommMessage =
130 serde_json::from_str(message).map_err(|e| ReceiveError::UnknownFormat(e.into()))?;
131 return Ok(Message::PlainJson {
132 header: plain_message.header,
133 body: plain_message.body.map(|r| r.get()).unwrap_or("null").to_owned(),
134 });
135 }
136 Err(ReceiveError::UnknownFormat(anyhow!("Expected JSON as JWE, JWS or plain DIDComm")))
137 }
138
139 pub fn header(&self) -> &DidCommHeader {
141 match self {
142 Message::PlainJson { header, body: _ } => header,
143 Message::SignedJson { sender: _, header, body: _ } => header,
144 Message::AnonCryptJson { header, body: _ } => header,
145 Message::AuthCryptJson { sender: _, header, body: _ } => header,
146 }
147 }
148
149 pub fn body(&self) -> &str {
151 match self {
152 Message::PlainJson { header: _, body } => body,
153 Message::SignedJson { sender: _, header: _, body } => body,
154 Message::AnonCryptJson { header: _, body } => body,
155 Message::AuthCryptJson { sender: _, header: _, body } => body,
156 }
157 }
158
159 pub fn body_deserialize<T: DeserializeOwned>(&self) -> Result<T, anyhow::Error> {
161 Ok(from_json_string(self.body())?)
162 }
163
164 pub fn is_validated_sender(&self) -> bool {
166 self.sender().is_some()
167 }
168
169 pub fn sender(&self) -> Option<&Did> {
171 match self {
172 Message::AuthCryptJson { sender, header, body: _ } if Some(sender) == header.from.as_ref() => Some(sender),
173 Message::SignedJson { sender, header, body: _ } if Some(sender) == header.from.as_ref() => Some(sender),
174 _ => None,
175 }
176 }
177
178 pub fn into_inner(self) -> (DidCommHeader, String) {
180 match self {
181 Message::PlainJson { header, body } => (header, body),
182 Message::SignedJson { sender: _, header, body } => (header, body),
183 Message::AnonCryptJson { header, body } => (header, body),
184 Message::AuthCryptJson { sender: _, header, body } => (header, body),
185 }
186 }
187}
188
189#[derive(Serialize, Deserialize, Debug)]
193struct UnknownReceivedMessage<'a> {
194 #[serde(borrow)]
195 pub signature: Option<&'a RawValue>,
196
197 #[serde(borrow)]
198 pub signatures: Option<&'a RawValue>,
199
200 #[serde(borrow)]
201 pub iv: Option<&'a RawValue>,
202}
203
204fn get_message_type(message: &str) -> Result<MessageType, anyhow::Error> {
208 let to_check: UnknownReceivedMessage = serde_json::from_str(message)?;
210 if to_check.iv.is_some() {
211 return Ok(MessageType::DidCommJwe);
212 }
213 if to_check.signatures.is_some() || to_check.signature.is_some() {
214 return Ok(MessageType::DidCommJws);
215 }
216 let didcomm_message: Option<didcomm_rs::Message> = serde_json::from_str(message).ok();
217 if let Some(didcomm_message) = didcomm_message {
218 return Ok(didcomm_message.get_jwm_header().typ.clone());
219 }
220 let _plain_message: DidCommMessage = serde_json::from_str(message)?;
221 Ok(MessageType::DidCommRaw)
222}
223
224async fn verify_signing_identity<I>(
229 sender_resolver: &I,
230 header: &DidCommHeader,
231 message: &str,
232) -> Result<Did, ReceiveError>
233where
234 I: IdentityResolver + Send + Sync + 'static,
235{
236 if let Some(from) = &header.from {
237 let sender_identity = sender_resolver
239 .resolve(from)
240 .await
241 .map_err(|e| ReceiveError::BadDid(from.to_owned(), e.into()))?;
242 let sender_context = sender_identity
243 .didcomm_public()
244 .ok_or_else(|| ReceiveError::BadDid(from.to_owned(), anyhow!("No didcomm public context.")))?;
245 let sender_public_key = sender_context
246 .verification_method()
247 .public_key_bytes()
248 .map_err(|err| ReceiveError::BadDid(from.to_owned(), err))?;
249 let sender_kid = hex::encode(&sender_public_key);
250
251 let jws: Jws = serde_json::from_str(message).map_err(|e| ReceiveError::UnknownFormat(e.into()))?;
253 let signatures = if let Some(signatures) = jws.signatures {
254 signatures
255 } else if let Some(signature) = jws.signature {
256 vec![signature]
257 } else {
258 vec![]
259 };
260 for signature in signatures {
261 if let Some(kid) = &signature.get_kid() {
262 if kid == &sender_kid || kid == sender_identity.identity() {
263 return Ok(from.clone());
264 }
265 }
266 }
267 Err(ReceiveError::InvalidSigningKeyId(anyhow!("Can not match from header")))
268 } else {
269 Err(ReceiveError::UnknownFormat(anyhow!("No from header")))
270 }
271}
272
273#[derive(Debug, Serialize, Deserialize)]
274struct DidCommMessage<'a> {
275 #[serde(flatten)]
276 header: DidCommHeader,
277 #[serde(borrow)]
278 body: Option<&'a RawValue>,
279}