1use crate::agent_key::VerificationKey;
8use crate::error::{Error, Result};
9use crate::message::{Jwe, Jws, SecurityMode};
10use async_trait::async_trait;
11use base64::Engine;
12use serde::de::DeserializeOwned;
13use serde::Serialize;
14use serde_json::Value;
15use std::any::Any;
16use std::fmt::Debug;
17use std::sync::Arc;
18use tap_msg::didcomm::{PlainMessage, PlainMessageExt};
19use tap_msg::message::TapMessage;
20use uuid::Uuid;
21
22#[derive(Debug, Clone)]
25pub struct UnpackedMessage {
26 pub plain_message: PlainMessage,
28 pub tap_message: Option<TapMessage>,
30}
31
32impl UnpackedMessage {
33 pub fn new(plain_message: PlainMessage) -> Self {
35 let tap_message = TapMessage::from_plain_message(&plain_message).ok();
36 Self {
37 plain_message,
38 tap_message,
39 }
40 }
41
42 pub fn as_typed<T: tap_msg::TapMessageBody>(&self) -> Result<PlainMessage<T>> {
44 self.plain_message
45 .clone()
46 .parse_as()
47 .map_err(|e| Error::Serialization(e.to_string()))
48 }
49
50 pub fn into_typed(self) -> PlainMessage<Value> {
52 self.plain_message.into_typed()
53 }
54}
55
56#[derive(Debug, thiserror::Error)]
58pub enum MessageError {
59 #[error("Serialization error: {0}")]
60 Serialization(#[from] serde_json::Error),
61
62 #[error("Key manager error: {0}")]
63 KeyManager(String),
64
65 #[error("Crypto operation failed: {0}")]
66 Crypto(String),
67
68 #[error("Invalid message format: {0}")]
69 InvalidFormat(String),
70
71 #[error("Unsupported security mode: {0:?}")]
72 UnsupportedSecurityMode(SecurityMode),
73
74 #[error("Missing required parameter: {0}")]
75 MissingParameter(String),
76
77 #[error("Key not found: {0}")]
78 KeyNotFound(String),
79
80 #[error("Verification failed")]
81 VerificationFailed,
82
83 #[error("Decryption failed")]
84 DecryptionFailed,
85}
86
87impl From<MessageError> for Error {
88 fn from(err: MessageError) -> Self {
89 match err {
90 MessageError::Serialization(e) => Error::Serialization(e.to_string()),
91 MessageError::KeyManager(e) => Error::Cryptography(e),
92 MessageError::Crypto(e) => Error::Cryptography(e),
93 MessageError::InvalidFormat(e) => Error::Validation(e),
94 MessageError::UnsupportedSecurityMode(mode) => {
95 Error::Validation(format!("Unsupported security mode: {:?}", mode))
96 }
97 MessageError::MissingParameter(e) => {
98 Error::Validation(format!("Missing parameter: {}", e))
99 }
100 MessageError::KeyNotFound(e) => Error::Cryptography(format!("Key not found: {}", e)),
101 MessageError::VerificationFailed => {
102 Error::Cryptography("Verification failed".to_string())
103 }
104 MessageError::DecryptionFailed => Error::Cryptography("Decryption failed".to_string()),
105 }
106 }
107}
108
109#[derive(Debug, Clone)]
111pub struct PackOptions {
112 pub security_mode: SecurityMode,
114 pub recipient_kid: Option<String>,
116 pub sender_kid: Option<String>,
118}
119
120impl Default for PackOptions {
121 fn default() -> Self {
122 Self::new()
123 }
124}
125
126impl PackOptions {
127 pub fn new() -> Self {
129 Self {
130 security_mode: SecurityMode::Plain,
131 recipient_kid: None,
132 sender_kid: None,
133 }
134 }
135
136 pub fn with_plain(mut self) -> Self {
138 self.security_mode = SecurityMode::Plain;
139 self
140 }
141
142 pub fn with_sign(mut self, sender_kid: &str) -> Self {
144 self.security_mode = SecurityMode::Signed;
145 self.sender_kid = Some(sender_kid.to_string());
146 self
147 }
148
149 pub fn with_auth_crypt(mut self, sender_kid: &str, recipient_jwk: &serde_json::Value) -> Self {
151 self.security_mode = SecurityMode::AuthCrypt;
152 self.sender_kid = Some(sender_kid.to_string());
153
154 if let Some(kid) = recipient_jwk.get("kid").and_then(|k| k.as_str()) {
156 self.recipient_kid = Some(kid.to_string());
157 }
158
159 self
160 }
161
162 pub fn security_mode(&self) -> SecurityMode {
164 self.security_mode
165 }
166}
167
168#[derive(Debug, Clone)]
170pub struct UnpackOptions {
171 pub expected_security_mode: SecurityMode,
173 pub expected_recipient_kid: Option<String>,
175 pub require_signature: bool,
177}
178
179impl Default for UnpackOptions {
180 fn default() -> Self {
181 Self::new()
182 }
183}
184
185impl UnpackOptions {
186 pub fn new() -> Self {
188 Self {
189 expected_security_mode: SecurityMode::Any,
190 expected_recipient_kid: None,
191 require_signature: false,
192 }
193 }
194
195 pub fn with_require_signature(mut self, require: bool) -> Self {
197 self.require_signature = require;
198 self
199 }
200}
201
202#[async_trait]
204pub trait Packable<Output = String>: Sized {
205 async fn pack(
207 &self,
208 key_manager: &(impl KeyManagerPacking + ?Sized),
209 options: PackOptions,
210 ) -> Result<Output>;
211}
212
213#[async_trait]
215pub trait Unpackable<Input, Output = PlainMessage>: Sized {
216 async fn unpack(
218 packed_message: &Input,
219 key_manager: &(impl KeyManagerPacking + ?Sized),
220 options: UnpackOptions,
221 ) -> Result<Output>;
222}
223
224#[async_trait]
226pub trait KeyManagerPacking: Send + Sync + Debug {
227 async fn get_signing_key(
229 &self,
230 kid: &str,
231 ) -> Result<Arc<dyn crate::agent_key::SigningKey + Send + Sync>>;
232
233 async fn get_encryption_key(
235 &self,
236 kid: &str,
237 ) -> Result<Arc<dyn crate::agent_key::EncryptionKey + Send + Sync>>;
238
239 async fn get_decryption_key(
241 &self,
242 kid: &str,
243 ) -> Result<Arc<dyn crate::agent_key::DecryptionKey + Send + Sync>>;
244
245 async fn resolve_verification_key(
247 &self,
248 kid: &str,
249 ) -> Result<Arc<dyn VerificationKey + Send + Sync>>;
250}
251
252#[async_trait]
254impl Packable for PlainMessage {
255 async fn pack(
256 &self,
257 key_manager: &(impl KeyManagerPacking + ?Sized),
258 options: PackOptions,
259 ) -> Result<String> {
260 match options.security_mode {
261 SecurityMode::Plain => {
262 serde_json::to_string(self).map_err(|e| Error::Serialization(e.to_string()))
264 }
265 SecurityMode::Signed => {
266 let sender_kid = options.sender_kid.clone().ok_or_else(|| {
268 Error::Validation("Signed mode requires sender_kid".to_string())
269 })?;
270
271 let signing_key = key_manager.get_signing_key(&sender_kid).await?;
273
274 let payload =
276 serde_json::to_string(self).map_err(|e| Error::Serialization(e.to_string()))?;
277
278 let protected_header = crate::message::JwsProtected {
280 typ: crate::message::DIDCOMM_SIGNED.to_string(),
281 alg: String::new(), kid: sender_kid.clone(),
283 };
284
285 let jws = signing_key
287 .create_jws(payload.as_bytes(), Some(protected_header))
288 .await
289 .map_err(|e| Error::Cryptography(format!("Failed to create JWS: {}", e)))?;
290
291 serde_json::to_string(&jws).map_err(|e| Error::Serialization(e.to_string()))
293 }
294 SecurityMode::AuthCrypt => {
295 let sender_kid = options.sender_kid.clone().ok_or_else(|| {
297 Error::Validation("AuthCrypt mode requires sender_kid".to_string())
298 })?;
299
300 let recipient_kid = options.recipient_kid.clone().ok_or_else(|| {
301 Error::Validation("AuthCrypt mode requires recipient_kid".to_string())
302 })?;
303
304 let encryption_key = key_manager.get_encryption_key(&sender_kid).await?;
306
307 let recipient_key = key_manager.resolve_verification_key(&recipient_kid).await?;
309
310 let plaintext =
312 serde_json::to_string(self).map_err(|e| Error::Serialization(e.to_string()))?;
313
314 let jwe = encryption_key
316 .create_jwe(plaintext.as_bytes(), &[recipient_key], None)
317 .await
318 .map_err(|e| Error::Cryptography(format!("Failed to create JWE: {}", e)))?;
319
320 serde_json::to_string(&jwe).map_err(|e| Error::Serialization(e.to_string()))
322 }
323 SecurityMode::Any => {
324 Err(Error::Validation(
326 "SecurityMode::Any is not valid for packing".to_string(),
327 ))
328 }
329 }
330 }
331}
332
333pub async fn pack_any<T>(
336 obj: &T,
337 key_manager: &(impl KeyManagerPacking + ?Sized),
338 options: PackOptions,
339) -> Result<String>
340where
341 T: Serialize + Send + Sync + std::fmt::Debug + 'static + Sized,
342{
343 if obj.type_id() == std::any::TypeId::of::<PlainMessage>() {
347 let value = serde_json::to_value(obj).map_err(|e| Error::Serialization(e.to_string()))?;
349 let plain_msg: PlainMessage =
350 serde_json::from_value(value).map_err(|e| Error::Serialization(e.to_string()))?;
351 return plain_msg.pack(key_manager, options).await;
352 }
353
354 match options.security_mode {
356 SecurityMode::Plain => {
357 serde_json::to_string(obj).map_err(|e| Error::Serialization(e.to_string()))
359 }
360 SecurityMode::Signed => {
361 let sender_kid = options
363 .sender_kid
364 .clone()
365 .ok_or_else(|| Error::Validation("Signed mode requires sender_kid".to_string()))?;
366
367 let signing_key = key_manager.get_signing_key(&sender_kid).await?;
369
370 let value =
372 serde_json::to_value(obj).map_err(|e| Error::Serialization(e.to_string()))?;
373
374 let obj = value
376 .as_object()
377 .ok_or_else(|| Error::Validation("Message is not a JSON object".to_string()))?;
378
379 let id_string = obj
381 .get("id")
382 .map(|v| v.as_str().unwrap_or_default().to_string())
383 .unwrap_or_else(|| Uuid::new_v4().to_string());
384 let id = id_string.as_str();
385
386 let msg_type = obj
388 .get("type")
389 .and_then(|v| v.as_str())
390 .unwrap_or("https://tap.rsvp/schema/1.0/message");
391
392 let from = options.sender_kid.as_ref().map(|kid| {
394 kid.split('#').next().unwrap_or(kid).to_string()
396 });
397
398 let to = if let Some(kid) = &options.recipient_kid {
399 let did = kid.split('#').next().unwrap_or(kid).to_string();
401 vec![did]
402 } else {
403 vec![]
404 };
405
406 let plain_message = PlainMessage {
408 id: id.to_string(),
409 typ: "application/didcomm-plain+json".to_string(),
410 type_: msg_type.to_string(),
411 body: value,
412 from: from.unwrap_or_default(),
413 to,
414 thid: None,
415 pthid: None,
416 created_time: Some(chrono::Utc::now().timestamp() as u64),
417 expires_time: None,
418 from_prior: None,
419 attachments: None,
420 extra_headers: std::collections::HashMap::new(),
421 };
422
423 let payload = serde_json::to_string(&plain_message)
425 .map_err(|e| Error::Serialization(e.to_string()))?;
426
427 let protected_header = crate::message::JwsProtected {
429 typ: crate::message::DIDCOMM_SIGNED.to_string(),
430 alg: String::new(), kid: sender_kid.clone(),
432 };
433
434 let jws = signing_key
436 .create_jws(payload.as_bytes(), Some(protected_header))
437 .await
438 .map_err(|e| Error::Cryptography(format!("Failed to create JWS: {}", e)))?;
439
440 serde_json::to_string(&jws).map_err(|e| Error::Serialization(e.to_string()))
442 }
443 SecurityMode::AuthCrypt => {
444 let sender_kid = options.sender_kid.clone().ok_or_else(|| {
446 Error::Validation("AuthCrypt mode requires sender_kid".to_string())
447 })?;
448
449 let recipient_kid = options.recipient_kid.clone().ok_or_else(|| {
450 Error::Validation("AuthCrypt mode requires recipient_kid".to_string())
451 })?;
452
453 let encryption_key = key_manager.get_encryption_key(&sender_kid).await?;
455
456 let recipient_key = key_manager.resolve_verification_key(&recipient_kid).await?;
458
459 let value =
461 serde_json::to_value(obj).map_err(|e| Error::Serialization(e.to_string()))?;
462
463 let obj = value
465 .as_object()
466 .ok_or_else(|| Error::Validation("Message is not a JSON object".to_string()))?;
467
468 let id_string = obj
470 .get("id")
471 .map(|v| v.as_str().unwrap_or_default().to_string())
472 .unwrap_or_else(|| Uuid::new_v4().to_string());
473 let id = id_string.as_str();
474
475 let msg_type = obj
477 .get("type")
478 .and_then(|v| v.as_str())
479 .unwrap_or("https://tap.rsvp/schema/1.0/message");
480
481 let from = options.sender_kid.as_ref().map(|kid| {
483 kid.split('#').next().unwrap_or(kid).to_string()
485 });
486
487 let to = if let Some(kid) = &options.recipient_kid {
488 let did = kid.split('#').next().unwrap_or(kid).to_string();
490 vec![did]
491 } else {
492 vec![]
493 };
494
495 let plain_message = PlainMessage {
497 id: id.to_string(),
498 typ: "application/didcomm-plain+json".to_string(),
499 type_: msg_type.to_string(),
500 body: value,
501 from: from.unwrap_or_default(),
502 to,
503 thid: None,
504 pthid: None,
505 created_time: Some(chrono::Utc::now().timestamp() as u64),
506 expires_time: None,
507 from_prior: None,
508 attachments: None,
509 extra_headers: std::collections::HashMap::new(),
510 };
511
512 let plaintext = serde_json::to_string(&plain_message)
514 .map_err(|e| Error::Serialization(e.to_string()))?;
515
516 let jwe = encryption_key
518 .create_jwe(plaintext.as_bytes(), &[recipient_key], None)
519 .await
520 .map_err(|e| Error::Cryptography(format!("Failed to create JWE: {}", e)))?;
521
522 serde_json::to_string(&jwe).map_err(|e| Error::Serialization(e.to_string()))
524 }
525 SecurityMode::Any => {
526 Err(Error::Validation(
528 "SecurityMode::Any is not valid for packing".to_string(),
529 ))
530 }
531 }
532}
533
534#[async_trait]
536impl<T: DeserializeOwned + Send + 'static> Unpackable<Jws, T> for Jws {
537 async fn unpack(
538 packed_message: &Jws,
539 key_manager: &(impl KeyManagerPacking + ?Sized),
540 _options: UnpackOptions,
541 ) -> Result<T> {
542 let payload_bytes = base64::engine::general_purpose::STANDARD
544 .decode(&packed_message.payload)
545 .map_err(|e| Error::Cryptography(format!("Failed to decode JWS payload: {}", e)))?;
546
547 let payload_str = String::from_utf8(payload_bytes)
549 .map_err(|e| Error::Validation(format!("Invalid UTF-8 in payload: {}", e)))?;
550
551 let plain_message: PlainMessage =
553 serde_json::from_str(&payload_str).map_err(|e| Error::Serialization(e.to_string()))?;
554
555 let mut verified = false;
557
558 for signature in &packed_message.signatures {
559 let protected_bytes = base64::engine::general_purpose::STANDARD
561 .decode(&signature.protected)
562 .map_err(|e| {
563 Error::Cryptography(format!("Failed to decode protected header: {}", e))
564 })?;
565
566 let protected: crate::message::JwsProtected = serde_json::from_slice(&protected_bytes)
568 .map_err(|e| {
569 Error::Serialization(format!("Failed to parse protected header: {}", e))
570 })?;
571
572 let kid = match signature.get_kid() {
574 Some(kid) => kid,
575 None => continue, };
577
578 let verification_key = match key_manager.resolve_verification_key(&kid).await {
580 Ok(key) => key,
581 Err(_) => continue, };
583
584 let signature_bytes = base64::engine::general_purpose::STANDARD
586 .decode(&signature.signature)
587 .map_err(|e| Error::Cryptography(format!("Failed to decode signature: {}", e)))?;
588
589 let signing_input = format!("{}.{}", signature.protected, packed_message.payload);
591
592 match verification_key
594 .verify_signature(signing_input.as_bytes(), &signature_bytes, &protected)
595 .await
596 {
597 Ok(true) => {
598 verified = true;
599 break;
600 }
601 _ => continue,
602 }
603 }
604
605 if !verified {
606 return Err(Error::Cryptography(
607 "Signature verification failed".to_string(),
608 ));
609 }
610
611 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<PlainMessage>() {
613 let result = serde_json::to_value(plain_message).unwrap();
615 return serde_json::from_value(result).map_err(|e| Error::Serialization(e.to_string()));
616 }
617
618 serde_json::from_value(plain_message.body).map_err(|e| Error::Serialization(e.to_string()))
620 }
621}
622
623#[async_trait]
625impl<T: DeserializeOwned + Send + 'static> Unpackable<Jwe, T> for Jwe {
626 async fn unpack(
627 packed_message: &Jwe,
628 key_manager: &(impl KeyManagerPacking + ?Sized),
629 options: UnpackOptions,
630 ) -> Result<T> {
631 let recipients = if let Some(kid) = &options.expected_recipient_kid {
633 packed_message
635 .recipients
636 .iter()
637 .filter(|r| r.header.kid == *kid)
638 .collect::<Vec<_>>()
639 } else {
640 packed_message.recipients.iter().collect::<Vec<_>>()
642 };
643
644 for recipient in recipients {
646 let kid = &recipient.header.kid;
648
649 let decryption_key = match key_manager.get_decryption_key(kid).await {
651 Ok(key) => key,
652 Err(_) => continue, };
654
655 match decryption_key.unwrap_jwe(packed_message).await {
657 Ok(plaintext) => {
658 let plaintext_str = String::from_utf8(plaintext).map_err(|e| {
660 Error::Validation(format!("Invalid UTF-8 in plaintext: {}", e))
661 })?;
662
663 let plain_message: PlainMessage = match serde_json::from_str(&plaintext_str) {
665 Ok(msg) => msg,
666 Err(e) => {
667 return Err(Error::Serialization(e.to_string()));
668 }
669 };
670
671 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<PlainMessage>() {
673 let result = serde_json::to_value(plain_message).unwrap();
675 return serde_json::from_value(result)
676 .map_err(|e| Error::Serialization(e.to_string()));
677 }
678
679 return serde_json::from_value(plain_message.body)
681 .map_err(|e| Error::Serialization(e.to_string()));
682 }
683 Err(_) => continue, }
685 }
686
687 Err(Error::Cryptography("Failed to decrypt message".to_string()))
689 }
690}
691
692#[async_trait]
694impl<T: DeserializeOwned + Send + 'static> Unpackable<String, T> for String {
695 async fn unpack(
696 packed_message: &String,
697 key_manager: &(impl KeyManagerPacking + ?Sized),
698 options: UnpackOptions,
699 ) -> Result<T> {
700 if let Ok(value) = serde_json::from_str::<Value>(packed_message) {
702 if value.get("payload").is_some() && value.get("signatures").is_some() {
704 let jws: Jws = serde_json::from_str(packed_message)
706 .map_err(|e| Error::Serialization(e.to_string()))?;
707
708 return Jws::unpack(&jws, key_manager, options).await;
709 }
710
711 if value.get("ciphertext").is_some()
713 && value.get("protected").is_some()
714 && value.get("recipients").is_some()
715 {
716 let jwe: Jwe = serde_json::from_str(packed_message)
718 .map_err(|e| Error::Serialization(e.to_string()))?;
719
720 return Jwe::unpack(&jwe, key_manager, options).await;
721 }
722
723 if value.get("body").is_some() && value.get("type").is_some() {
725 let plain: PlainMessage = serde_json::from_str(packed_message)
727 .map_err(|e| Error::Serialization(e.to_string()))?;
728
729 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<PlainMessage>() {
731 let result = serde_json::to_value(plain).unwrap();
733 return serde_json::from_value(result)
734 .map_err(|e| Error::Serialization(e.to_string()));
735 }
736
737 return serde_json::from_value(plain.body)
739 .map_err(|e| Error::Serialization(e.to_string()));
740 }
741
742 return serde_json::from_value(value).map_err(|e| Error::Serialization(e.to_string()));
744 }
745
746 Err(Error::Validation("Message is not valid JSON".to_string()))
748 }
749}
750
751#[async_trait]
753impl Unpackable<String, UnpackedMessage> for String {
754 async fn unpack(
755 packed_message: &String,
756 key_manager: &(impl KeyManagerPacking + ?Sized),
757 options: UnpackOptions,
758 ) -> Result<UnpackedMessage> {
759 let plain_message: PlainMessage =
761 String::unpack(packed_message, key_manager, options).await?;
762
763 Ok(UnpackedMessage::new(plain_message))
765 }
766}
767
768#[async_trait]
770impl Unpackable<Jws, UnpackedMessage> for Jws {
771 async fn unpack(
772 packed_message: &Jws,
773 key_manager: &(impl KeyManagerPacking + ?Sized),
774 options: UnpackOptions,
775 ) -> Result<UnpackedMessage> {
776 let plain_message: PlainMessage = Jws::unpack(packed_message, key_manager, options).await?;
778
779 Ok(UnpackedMessage::new(plain_message))
781 }
782}
783
784#[async_trait]
786impl Unpackable<Jwe, UnpackedMessage> for Jwe {
787 async fn unpack(
788 packed_message: &Jwe,
789 key_manager: &(impl KeyManagerPacking + ?Sized),
790 options: UnpackOptions,
791 ) -> Result<UnpackedMessage> {
792 let plain_message: PlainMessage = Jwe::unpack(packed_message, key_manager, options).await?;
794
795 Ok(UnpackedMessage::new(plain_message))
797 }
798}
799#[cfg(test)]
800mod tests {
801 use super::*;
802 use crate::agent_key_manager::AgentKeyManagerBuilder;
803 use crate::did::{DIDGenerationOptions, KeyType};
804 use crate::key_manager::KeyManager;
805 use std::sync::Arc;
806 use tap_msg::didcomm::PlainMessage;
807 use tap_msg::message::agent::TapParticipant;
808
809 #[tokio::test]
810 async fn test_plain_message_pack_unpack() {
811 let key_manager = Arc::new(AgentKeyManagerBuilder::new().build().unwrap());
813 let key = key_manager
814 .generate_key(DIDGenerationOptions {
815 key_type: KeyType::Ed25519,
816 })
817 .unwrap();
818
819 let message = PlainMessage {
821 id: "test-message-1".to_string(),
822 typ: "application/didcomm-plain+json".to_string(),
823 type_: "https://example.org/test".to_string(),
824 body: serde_json::json!({
825 "content": "Hello, World!"
826 }),
827 from: key.did.clone(),
828 to: vec!["did:example:bob".to_string()],
829 thid: None,
830 pthid: None,
831 created_time: Some(1234567890),
832 expires_time: None,
833 from_prior: None,
834 attachments: None,
835 extra_headers: Default::default(),
836 };
837
838 let pack_options = PackOptions::new().with_plain();
840 let packed = message.pack(&*key_manager, pack_options).await.unwrap();
841
842 let unpack_options = UnpackOptions::new();
844 let unpacked: PlainMessage = String::unpack(&packed, &*key_manager, unpack_options)
845 .await
846 .unwrap();
847
848 assert_eq!(unpacked.id, message.id);
850 assert_eq!(unpacked.type_, message.type_);
851 assert_eq!(unpacked.body, message.body);
852 assert_eq!(unpacked.from, message.from);
853 assert_eq!(unpacked.to, message.to);
854 }
855
856 #[tokio::test]
857 async fn test_jws_message_pack_unpack() {
858 let key_manager = Arc::new(AgentKeyManagerBuilder::new().build().unwrap());
860 let key = key_manager
861 .generate_key(DIDGenerationOptions {
862 key_type: KeyType::Ed25519,
863 })
864 .unwrap();
865
866 let sender_kid = format!("{}#keys-1", key.did);
867
868 let message = PlainMessage {
870 id: "test-message-2".to_string(),
871 typ: "application/didcomm-plain+json".to_string(),
872 type_: "https://example.org/test".to_string(),
873 body: serde_json::json!({
874 "content": "Signed message"
875 }),
876 from: key.did.clone(),
877 to: vec!["did:example:bob".to_string()],
878 thid: None,
879 pthid: None,
880 created_time: Some(1234567890),
881 expires_time: None,
882 from_prior: None,
883 attachments: None,
884 extra_headers: Default::default(),
885 };
886
887 let pack_options = PackOptions::new().with_sign(&sender_kid);
889 let packed = message.pack(&*key_manager, pack_options).await.unwrap();
890
891 let jws: Jws = serde_json::from_str(&packed).unwrap();
893 assert!(!jws.signatures.is_empty());
894
895 let protected_header = jws.signatures[0].get_protected_header().unwrap();
897 assert_eq!(protected_header.kid, sender_kid);
898 assert_eq!(protected_header.typ, "application/didcomm-signed+json");
899 assert_eq!(protected_header.alg, "EdDSA");
900
901 let unpack_options = UnpackOptions::new();
903 let unpacked: PlainMessage = String::unpack(&packed, &*key_manager, unpack_options)
904 .await
905 .unwrap();
906
907 assert_eq!(unpacked.id, message.id);
909 assert_eq!(unpacked.type_, message.type_);
910 assert_eq!(unpacked.body, message.body);
911 assert_eq!(unpacked.from, message.from);
912 assert_eq!(unpacked.to, message.to);
913 }
914
915 #[tokio::test]
916 async fn test_different_key_types_jws() {
917 let key_types = vec![KeyType::Ed25519];
919
920 for key_type in key_types {
921 let key_manager = Arc::new(AgentKeyManagerBuilder::new().build().unwrap());
923 let key = key_manager
924 .generate_key(DIDGenerationOptions { key_type })
925 .unwrap();
926
927 let sender_kid = format!("{}#keys-1", key.did);
928
929 let message = PlainMessage {
931 id: format!("test-{:?}", key_type),
932 typ: "application/didcomm-plain+json".to_string(),
933 type_: "https://example.org/test".to_string(),
934 body: serde_json::json!({
935 "content": format!("Signed with {:?}", key_type)
936 }),
937 from: key.did.clone(),
938 to: vec!["did:example:bob".to_string()],
939 thid: None,
940 pthid: None,
941 created_time: Some(1234567890),
942 expires_time: None,
943 from_prior: None,
944 attachments: None,
945 extra_headers: Default::default(),
946 };
947
948 let pack_options = PackOptions::new().with_sign(&sender_kid);
950 let packed = message.pack(&*key_manager, pack_options).await.unwrap();
951
952 let jws: Jws = serde_json::from_str(&packed).unwrap();
954 assert!(!jws.signatures.is_empty());
955
956 let protected_header = jws.signatures[0].get_protected_header().unwrap();
958 assert_eq!(protected_header.kid, sender_kid);
959
960 let expected_alg = match key_type {
962 KeyType::Ed25519 => "EdDSA",
963 KeyType::P256 => "ES256",
964 KeyType::Secp256k1 => "ES256K",
965 };
966 assert_eq!(protected_header.alg, expected_alg);
967
968 let unpack_options = UnpackOptions::new();
970 let unpacked: PlainMessage = String::unpack(&packed, &*key_manager, unpack_options)
971 .await
972 .unwrap();
973
974 assert_eq!(unpacked.id, message.id);
975 assert_eq!(unpacked.body, message.body);
976 }
977 }
978
979 #[tokio::test]
980 async fn test_unpack_with_wrong_signature() {
981 let key_manager1 = Arc::new(AgentKeyManagerBuilder::new().build().unwrap());
983 let key1 = key_manager1
984 .generate_key(DIDGenerationOptions {
985 key_type: KeyType::Ed25519,
986 })
987 .unwrap();
988
989 let key_manager2 = Arc::new(AgentKeyManagerBuilder::new().build().unwrap());
990 let _key2 = key_manager2
991 .generate_key(DIDGenerationOptions {
992 key_type: KeyType::Ed25519,
993 })
994 .unwrap();
995
996 let message = PlainMessage {
998 id: "test-wrong-sig".to_string(),
999 typ: "application/didcomm-plain+json".to_string(),
1000 type_: "https://example.org/test".to_string(),
1001 body: serde_json::json!({
1002 "content": "Test wrong signature"
1003 }),
1004 from: key1.did.clone(),
1005 to: vec!["did:example:bob".to_string()],
1006 thid: None,
1007 pthid: None,
1008 created_time: Some(1234567890),
1009 expires_time: None,
1010 from_prior: None,
1011 attachments: None,
1012 extra_headers: Default::default(),
1013 };
1014
1015 let sender_kid = format!("{}#keys-1", key1.did);
1016 let pack_options = PackOptions::new().with_sign(&sender_kid);
1017 let packed = message.pack(&*key_manager1, pack_options).await.unwrap();
1018
1019 let unpack_options = UnpackOptions::new();
1021 let result: Result<PlainMessage> =
1022 String::unpack(&packed, &*key_manager2, unpack_options).await;
1023
1024 assert!(result.is_err());
1025 }
1026
1027 #[tokio::test]
1028 async fn test_unpack_to_unpacked_message() {
1029 let key_manager = Arc::new(AgentKeyManagerBuilder::new().build().unwrap());
1031 let key = key_manager
1032 .generate_key(DIDGenerationOptions {
1033 key_type: KeyType::Ed25519,
1034 })
1035 .unwrap();
1036
1037 let message = PlainMessage {
1039 id: "test-transfer-1".to_string(),
1040 typ: "application/didcomm-plain+json".to_string(),
1041 type_: "https://tap.rsvp/schema/1.0#Transfer".to_string(),
1042 body: serde_json::json!({
1043 "@type": "https://tap.rsvp/schema/1.0#Transfer",
1044 "transaction_id": "test-tx-123",
1045 "asset": {
1046 "chain_id": {
1047 "namespace": "eip155",
1048 "reference": "1"
1049 },
1050 "namespace": "slip44",
1051 "reference": "60"
1052 },
1053 "originator": {
1054 "@id": key.did.clone()
1055 },
1056 "amount": "100",
1057 "agents": [],
1058 "memo": null,
1059 "beneficiary": null,
1060 "settlement_id": null,
1061 "connection_id": null,
1062 "metadata": {}
1063 }),
1064 from: key.did.clone(),
1065 to: vec!["did:example:bob".to_string()],
1066 thid: None,
1067 pthid: None,
1068 created_time: Some(1234567890),
1069 expires_time: None,
1070 from_prior: None,
1071 attachments: None,
1072 extra_headers: Default::default(),
1073 };
1074
1075 let pack_options = PackOptions::new().with_plain();
1077 let packed = message.pack(&*key_manager, pack_options).await.unwrap();
1078
1079 let unpack_options = UnpackOptions::new();
1081 let unpacked: UnpackedMessage = String::unpack(&packed, &*key_manager, unpack_options)
1082 .await
1083 .unwrap();
1084
1085 assert_eq!(unpacked.plain_message.id, message.id);
1087 assert_eq!(unpacked.plain_message.type_, message.type_);
1088
1089 assert!(unpacked.tap_message.is_some());
1091 match unpacked.tap_message.unwrap() {
1092 TapMessage::Transfer(transfer) => {
1093 assert_eq!(transfer.amount, "100");
1094 assert_eq!(transfer.originator.id(), key.did);
1095 }
1096 _ => panic!("Expected Transfer message"),
1097 }
1098 }
1099
1100 #[tokio::test]
1101 async fn test_unpack_invalid_tap_message() {
1102 let key_manager = Arc::new(AgentKeyManagerBuilder::new().build().unwrap());
1104 let key = key_manager
1105 .generate_key(DIDGenerationOptions {
1106 key_type: KeyType::Ed25519,
1107 })
1108 .unwrap();
1109
1110 let message = PlainMessage {
1112 id: "test-unknown-1".to_string(),
1113 typ: "application/didcomm-plain+json".to_string(),
1114 type_: "https://example.org/unknown#message".to_string(),
1115 body: serde_json::json!({
1116 "content": "Unknown message type"
1117 }),
1118 from: key.did.clone(),
1119 to: vec!["did:example:bob".to_string()],
1120 thid: None,
1121 pthid: None,
1122 created_time: Some(1234567890),
1123 expires_time: None,
1124 from_prior: None,
1125 attachments: None,
1126 extra_headers: Default::default(),
1127 };
1128
1129 let pack_options = PackOptions::new().with_plain();
1131 let packed = message.pack(&*key_manager, pack_options).await.unwrap();
1132
1133 let unpack_options = UnpackOptions::new();
1135 let unpacked: UnpackedMessage = String::unpack(&packed, &*key_manager, unpack_options)
1136 .await
1137 .unwrap();
1138
1139 assert_eq!(unpacked.plain_message.id, message.id);
1141
1142 assert!(unpacked.tap_message.is_none());
1144 }
1145}