tap_agent/
message_packing.rs

1//! Message Packing and Unpacking Utilities
2//!
3//! This module provides traits and implementations for standardizing
4//! how messages are prepared for transmission (packed) and processed
5//! upon receipt (unpacked).
6
7use 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/// Result of unpacking a message containing both the PlainMessage
23/// and the parsed TAP message
24#[derive(Debug, Clone)]
25pub struct UnpackedMessage {
26    /// The unpacked PlainMessage
27    pub plain_message: PlainMessage,
28    /// The parsed TAP message (if it could be parsed)
29    pub tap_message: Option<TapMessage>,
30}
31
32impl UnpackedMessage {
33    /// Create a new UnpackedMessage
34    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    /// Try to get the message as a specific typed message
43    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    /// Convert to a typed message with untyped body
51    pub fn into_typed(self) -> PlainMessage<Value> {
52        self.plain_message.into_typed()
53    }
54}
55
56/// Error type specific to message packing and unpacking
57#[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/// Options for packing a message
110#[derive(Debug, Clone)]
111pub struct PackOptions {
112    /// Security mode to use
113    pub security_mode: SecurityMode,
114    /// Key ID of the recipient (for JWE)
115    pub recipient_kid: Option<String>,
116    /// Key ID of the sender (for JWS and JWE)
117    pub sender_kid: Option<String>,
118}
119
120impl Default for PackOptions {
121    fn default() -> Self {
122        Self::new()
123    }
124}
125
126impl PackOptions {
127    /// Create new default packing options
128    pub fn new() -> Self {
129        Self {
130            security_mode: SecurityMode::Plain,
131            recipient_kid: None,
132            sender_kid: None,
133        }
134    }
135
136    /// Set to use plain mode (no security)
137    pub fn with_plain(mut self) -> Self {
138        self.security_mode = SecurityMode::Plain;
139        self
140    }
141
142    /// Set to use signed mode with the given sender key ID
143    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    /// Set to use auth-crypt mode with the given sender and recipient key IDs
150    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        // Extract kid from JWK if available
155        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    /// Get the security mode
163    pub fn security_mode(&self) -> SecurityMode {
164        self.security_mode
165    }
166}
167
168/// Options for unpacking a message
169#[derive(Debug, Clone)]
170pub struct UnpackOptions {
171    /// Expected security mode, or Any to try all modes
172    pub expected_security_mode: SecurityMode,
173    /// Expected recipient key ID
174    pub expected_recipient_kid: Option<String>,
175    /// Whether to require a valid signature
176    pub require_signature: bool,
177}
178
179impl Default for UnpackOptions {
180    fn default() -> Self {
181        Self::new()
182    }
183}
184
185impl UnpackOptions {
186    /// Create new default unpacking options
187    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    /// Set whether to require a valid signature
196    pub fn with_require_signature(mut self, require: bool) -> Self {
197        self.require_signature = require;
198        self
199    }
200}
201
202/// Trait for objects that can be packed for secure transmission
203#[async_trait]
204pub trait Packable<Output = String>: Sized {
205    /// Pack the object for secure transmission
206    async fn pack(
207        &self,
208        key_manager: &(impl KeyManagerPacking + ?Sized),
209        options: PackOptions,
210    ) -> Result<Output>;
211}
212
213/// Trait for objects that can be unpacked from a secure format
214#[async_trait]
215pub trait Unpackable<Input, Output = PlainMessage>: Sized {
216    /// Unpack the object from its secure format
217    async fn unpack(
218        packed_message: &Input,
219        key_manager: &(impl KeyManagerPacking + ?Sized),
220        options: UnpackOptions,
221    ) -> Result<Output>;
222}
223
224/// Interface required for key managers to support packing/unpacking
225#[async_trait]
226pub trait KeyManagerPacking: Send + Sync + Debug {
227    /// Get a signing key by ID
228    async fn get_signing_key(
229        &self,
230        kid: &str,
231    ) -> Result<Arc<dyn crate::agent_key::SigningKey + Send + Sync>>;
232
233    /// Get an encryption key by ID
234    async fn get_encryption_key(
235        &self,
236        kid: &str,
237    ) -> Result<Arc<dyn crate::agent_key::EncryptionKey + Send + Sync>>;
238
239    /// Get a decryption key by ID
240    async fn get_decryption_key(
241        &self,
242        kid: &str,
243    ) -> Result<Arc<dyn crate::agent_key::DecryptionKey + Send + Sync>>;
244
245    /// Resolve a verification key
246    async fn resolve_verification_key(
247        &self,
248        kid: &str,
249    ) -> Result<Arc<dyn VerificationKey + Send + Sync>>;
250}
251
252/// Implement Packable for PlainMessage
253#[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                // For plain mode, just serialize the PlainMessage
263                serde_json::to_string(self).map_err(|e| Error::Serialization(e.to_string()))
264            }
265            SecurityMode::Signed => {
266                // Signed mode requires a sender KID
267                let sender_kid = options.sender_kid.clone().ok_or_else(|| {
268                    Error::Validation("Signed mode requires sender_kid".to_string())
269                })?;
270
271                // Get the signing key
272                let signing_key = key_manager.get_signing_key(&sender_kid).await?;
273
274                // Prepare the message payload to sign
275                let payload =
276                    serde_json::to_string(self).map_err(|e| Error::Serialization(e.to_string()))?;
277
278                // Create protected header with the sender_kid
279                let protected_header = crate::message::JwsProtected {
280                    typ: crate::message::DIDCOMM_SIGNED.to_string(),
281                    alg: String::new(), // Will be set by create_jws based on key type
282                    kid: sender_kid.clone(),
283                };
284
285                // Create a JWS
286                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                // Serialize the JWS
292                serde_json::to_string(&jws).map_err(|e| Error::Serialization(e.to_string()))
293            }
294            SecurityMode::AuthCrypt => {
295                // AuthCrypt mode requires both sender and recipient KIDs
296                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                // Get the encryption key
305                let encryption_key = key_manager.get_encryption_key(&sender_kid).await?;
306
307                // Get the recipient's verification key
308                let recipient_key = key_manager.resolve_verification_key(&recipient_kid).await?;
309
310                // Serialize the message
311                let plaintext =
312                    serde_json::to_string(self).map_err(|e| Error::Serialization(e.to_string()))?;
313
314                // Create a JWE for the recipient
315                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                // Serialize the JWE
321                serde_json::to_string(&jwe).map_err(|e| Error::Serialization(e.to_string()))
322            }
323            SecurityMode::Any => {
324                // Any mode is not valid for packing, only for unpacking
325                Err(Error::Validation(
326                    "SecurityMode::Any is not valid for packing".to_string(),
327                ))
328            }
329        }
330    }
331}
332
333/// We can't implement Packable for all types due to the conflict with PlainMessage
334/// Instead, let's create a helper function:
335pub 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    // Skip attempt to implement Packable for generic types and use a helper function instead
344
345    // If the object is a PlainMessage, use PlainMessage's implementation
346    if obj.type_id() == std::any::TypeId::of::<PlainMessage>() {
347        // In this case, we can't easily downcast, so we'll serialize and deserialize
348        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    // Otherwise, implement the same logic here as in the PlainMessage implementation
355    match options.security_mode {
356        SecurityMode::Plain => {
357            // For plain mode, just serialize the object to JSON
358            serde_json::to_string(obj).map_err(|e| Error::Serialization(e.to_string()))
359        }
360        SecurityMode::Signed => {
361            // Signed mode requires a sender KID
362            let sender_kid = options
363                .sender_kid
364                .clone()
365                .ok_or_else(|| Error::Validation("Signed mode requires sender_kid".to_string()))?;
366
367            // Get the signing key
368            let signing_key = key_manager.get_signing_key(&sender_kid).await?;
369
370            // Convert to a Value first
371            let value =
372                serde_json::to_value(obj).map_err(|e| Error::Serialization(e.to_string()))?;
373
374            // Ensure it's an object
375            let obj = value
376                .as_object()
377                .ok_or_else(|| Error::Validation("Message is not a JSON object".to_string()))?;
378
379            // Extract ID, or generate one if missing
380            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            // Extract type, or use default
387            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            // Create sender/recipient lists
393            let from = options.sender_kid.as_ref().map(|kid| {
394                // Extract DID part from kid (assuming format is did#key-1)
395                kid.split('#').next().unwrap_or(kid).to_string()
396            });
397
398            let to = if let Some(kid) = &options.recipient_kid {
399                // Extract DID part from kid
400                let did = kid.split('#').next().unwrap_or(kid).to_string();
401                vec![did]
402            } else {
403                vec![]
404            };
405
406            // Create a PlainMessage
407            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            // Prepare the message payload to sign
424            let payload = serde_json::to_string(&plain_message)
425                .map_err(|e| Error::Serialization(e.to_string()))?;
426
427            // Create protected header with the sender_kid
428            let protected_header = crate::message::JwsProtected {
429                typ: crate::message::DIDCOMM_SIGNED.to_string(),
430                alg: String::new(), // Will be set by create_jws based on key type
431                kid: sender_kid.clone(),
432            };
433
434            // Create a JWS
435            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            // Serialize the JWS
441            serde_json::to_string(&jws).map_err(|e| Error::Serialization(e.to_string()))
442        }
443        SecurityMode::AuthCrypt => {
444            // AuthCrypt mode requires both sender and recipient KIDs
445            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            // Get the encryption key
454            let encryption_key = key_manager.get_encryption_key(&sender_kid).await?;
455
456            // Get the recipient's verification key
457            let recipient_key = key_manager.resolve_verification_key(&recipient_kid).await?;
458
459            // Convert to a Value first
460            let value =
461                serde_json::to_value(obj).map_err(|e| Error::Serialization(e.to_string()))?;
462
463            // Ensure it's an object
464            let obj = value
465                .as_object()
466                .ok_or_else(|| Error::Validation("Message is not a JSON object".to_string()))?;
467
468            // Extract ID, or generate one if missing
469            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            // Extract type, or use default
476            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            // Create sender/recipient lists
482            let from = options.sender_kid.as_ref().map(|kid| {
483                // Extract DID part from kid (assuming format is did#key-1)
484                kid.split('#').next().unwrap_or(kid).to_string()
485            });
486
487            let to = if let Some(kid) = &options.recipient_kid {
488                // Extract DID part from kid
489                let did = kid.split('#').next().unwrap_or(kid).to_string();
490                vec![did]
491            } else {
492                vec![]
493            };
494
495            // Create a PlainMessage
496            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            // Serialize the message
513            let plaintext = serde_json::to_string(&plain_message)
514                .map_err(|e| Error::Serialization(e.to_string()))?;
515
516            // Create a JWE for the recipient
517            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            // Serialize the JWE
523            serde_json::to_string(&jwe).map_err(|e| Error::Serialization(e.to_string()))
524        }
525        SecurityMode::Any => {
526            // Any mode is not valid for packing, only for unpacking
527            Err(Error::Validation(
528                "SecurityMode::Any is not valid for packing".to_string(),
529            ))
530        }
531    }
532}
533
534/// Implement Unpackable for JWS
535#[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        // Decode the payload
543        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        // Convert to string
548        let payload_str = String::from_utf8(payload_bytes)
549            .map_err(|e| Error::Validation(format!("Invalid UTF-8 in payload: {}", e)))?;
550
551        // Parse as PlainMessage first
552        let plain_message: PlainMessage =
553            serde_json::from_str(&payload_str).map_err(|e| Error::Serialization(e.to_string()))?;
554
555        // Verify signatures
556        let mut verified = false;
557
558        for signature in &packed_message.signatures {
559            // Decode the protected header
560            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            // Parse the protected header
567            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            // Get the key ID from protected header
573            let kid = match signature.get_kid() {
574                Some(kid) => kid,
575                None => continue, // Skip if no kid found
576            };
577
578            // Resolve the verification key
579            let verification_key = match key_manager.resolve_verification_key(&kid).await {
580                Ok(key) => key,
581                Err(_) => continue, // Skip key if we can't resolve it
582            };
583
584            // Decode the signature
585            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            // Create the signing input (protected.payload)
590            let signing_input = format!("{}.{}", signature.protected, packed_message.payload);
591
592            // Verify the signature
593            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 we want the PlainMessage itself, return it
612        if std::any::TypeId::of::<T>() == std::any::TypeId::of::<PlainMessage>() {
613            // This is safe because we've verified that T is PlainMessage
614            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        // Otherwise deserialize the body to the requested type
619        serde_json::from_value(plain_message.body).map_err(|e| Error::Serialization(e.to_string()))
620    }
621}
622
623/// Implement Unpackable for JWE
624#[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        // Find a recipient that matches our expected key, if any
632        let recipients = if let Some(kid) = &options.expected_recipient_kid {
633            // Filter to just the matching recipient
634            packed_message
635                .recipients
636                .iter()
637                .filter(|r| r.header.kid == *kid)
638                .collect::<Vec<_>>()
639        } else {
640            // Try all recipients
641            packed_message.recipients.iter().collect::<Vec<_>>()
642        };
643
644        // Try each recipient until we find one we can decrypt
645        for recipient in recipients {
646            // Get the recipient's key ID
647            let kid = &recipient.header.kid;
648
649            // Get the decryption key
650            let decryption_key = match key_manager.get_decryption_key(kid).await {
651                Ok(key) => key,
652                Err(_) => continue, // Skip if we don't have the key
653            };
654
655            // Try to decrypt
656            match decryption_key.unwrap_jwe(packed_message).await {
657                Ok(plaintext) => {
658                    // Convert to string
659                    let plaintext_str = String::from_utf8(plaintext).map_err(|e| {
660                        Error::Validation(format!("Invalid UTF-8 in plaintext: {}", e))
661                    })?;
662
663                    // Parse as PlainMessage
664                    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 we want the PlainMessage itself, return it
672                    if std::any::TypeId::of::<T>() == std::any::TypeId::of::<PlainMessage>() {
673                        // This is safe because we've verified that T is PlainMessage
674                        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                    // Otherwise deserialize the body to the requested type
680                    return serde_json::from_value(plain_message.body)
681                        .map_err(|e| Error::Serialization(e.to_string()));
682                }
683                Err(_) => continue, // Try next recipient
684            }
685        }
686
687        // If we get here, we couldn't decrypt for any recipient
688        Err(Error::Cryptography("Failed to decrypt message".to_string()))
689    }
690}
691
692/// Implement Unpackable for String (to handle any packed format)
693#[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        // Try to parse as JSON first
701        if let Ok(value) = serde_json::from_str::<Value>(packed_message) {
702            // Check if it's a JWS (has payload and signatures fields)
703            if value.get("payload").is_some() && value.get("signatures").is_some() {
704                // Parse as JWS
705                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            // Check if it's a JWE (has ciphertext, protected, and recipients fields)
712            if value.get("ciphertext").is_some()
713                && value.get("protected").is_some()
714                && value.get("recipients").is_some()
715            {
716                // Parse as JWE
717                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            // Check if it's a PlainMessage (has body and type fields)
724            if value.get("body").is_some() && value.get("type").is_some() {
725                // Parse as PlainMessage
726                let plain: PlainMessage = serde_json::from_str(packed_message)
727                    .map_err(|e| Error::Serialization(e.to_string()))?;
728
729                // If we want the PlainMessage itself, return it
730                if std::any::TypeId::of::<T>() == std::any::TypeId::of::<PlainMessage>() {
731                    // This is safe because we've verified that T is PlainMessage
732                    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                // Otherwise get the body
738                return serde_json::from_value(plain.body)
739                    .map_err(|e| Error::Serialization(e.to_string()));
740            }
741
742            // If it doesn't match any known format but is a valid JSON, try to parse directly
743            return serde_json::from_value(value).map_err(|e| Error::Serialization(e.to_string()));
744        }
745
746        // If not valid JSON, return an error
747        Err(Error::Validation("Message is not valid JSON".to_string()))
748    }
749}
750
751/// Implement Unpackable for String to UnpackedMessage
752#[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        // First unpack to PlainMessage
760        let plain_message: PlainMessage =
761            String::unpack(packed_message, key_manager, options).await?;
762
763        // Then create UnpackedMessage which will try to parse the TAP message
764        Ok(UnpackedMessage::new(plain_message))
765    }
766}
767
768/// Implement Unpackable for JWS to UnpackedMessage
769#[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        // First unpack to PlainMessage
777        let plain_message: PlainMessage = Jws::unpack(packed_message, key_manager, options).await?;
778
779        // Then create UnpackedMessage which will try to parse the TAP message
780        Ok(UnpackedMessage::new(plain_message))
781    }
782}
783
784/// Implement Unpackable for JWE to UnpackedMessage
785#[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        // First unpack to PlainMessage
793        let plain_message: PlainMessage = Jwe::unpack(packed_message, key_manager, options).await?;
794
795        // Then create UnpackedMessage which will try to parse the TAP message
796        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        // Create a key manager with a test key
812        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        // Create a test message
820        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        // Pack in plain mode
839        let pack_options = PackOptions::new().with_plain();
840        let packed = message.pack(&*key_manager, pack_options).await.unwrap();
841
842        // Unpack
843        let unpack_options = UnpackOptions::new();
844        let unpacked: PlainMessage = String::unpack(&packed, &*key_manager, unpack_options)
845            .await
846            .unwrap();
847
848        // Verify
849        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        // Create a key manager with a test key
859        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        // Create a test message
869        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        // Pack with signing
888        let pack_options = PackOptions::new().with_sign(&sender_kid);
889        let packed = message.pack(&*key_manager, pack_options).await.unwrap();
890
891        // Verify it's a JWS
892        let jws: Jws = serde_json::from_str(&packed).unwrap();
893        assert!(!jws.signatures.is_empty());
894
895        // Check the protected header has the correct kid
896        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        // Unpack
902        let unpack_options = UnpackOptions::new();
903        let unpacked: PlainMessage = String::unpack(&packed, &*key_manager, unpack_options)
904            .await
905            .unwrap();
906
907        // Verify
908        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        // Test with different key types
918        let key_types = vec![KeyType::Ed25519];
919
920        for key_type in key_types {
921            // Create a key manager with a test key
922            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            // Create a test message
930            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            // Pack with signing
949            let pack_options = PackOptions::new().with_sign(&sender_kid);
950            let packed = message.pack(&*key_manager, pack_options).await.unwrap();
951
952            // Verify it's a JWS
953            let jws: Jws = serde_json::from_str(&packed).unwrap();
954            assert!(!jws.signatures.is_empty());
955
956            // Check the protected header
957            let protected_header = jws.signatures[0].get_protected_header().unwrap();
958            assert_eq!(protected_header.kid, sender_kid);
959
960            // Check algorithm matches key type
961            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            // Unpack and verify
969            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        // Create two different key managers
982        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        // Create and sign a message with key1
997        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        // Try to unpack with key_manager2 (should fail)
1020        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        // Create a key manager with a test key
1030        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        // Create a TAP transfer message
1038        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        // Pack in plain mode
1076        let pack_options = PackOptions::new().with_plain();
1077        let packed = message.pack(&*key_manager, pack_options).await.unwrap();
1078
1079        // Unpack to UnpackedMessage
1080        let unpack_options = UnpackOptions::new();
1081        let unpacked: UnpackedMessage = String::unpack(&packed, &*key_manager, unpack_options)
1082            .await
1083            .unwrap();
1084
1085        // Verify PlainMessage
1086        assert_eq!(unpacked.plain_message.id, message.id);
1087        assert_eq!(unpacked.plain_message.type_, message.type_);
1088
1089        // Verify TAP message was parsed
1090        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        // Create a key manager with a test key
1103        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        // Create a message with an unknown type
1111        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        // Pack in plain mode
1130        let pack_options = PackOptions::new().with_plain();
1131        let packed = message.pack(&*key_manager, pack_options).await.unwrap();
1132
1133        // Unpack to UnpackedMessage
1134        let unpack_options = UnpackOptions::new();
1135        let unpacked: UnpackedMessage = String::unpack(&packed, &*key_manager, unpack_options)
1136            .await
1137            .unwrap();
1138
1139        // Verify PlainMessage was unpacked
1140        assert_eq!(unpacked.plain_message.id, message.id);
1141
1142        // Verify TAP message parsing failed (unknown type)
1143        assert!(unpacked.tap_message.is_none());
1144    }
1145}