tap_agent/
message.rs

1//! Message types and utilities for the TAP Agent.
2//!
3//! This module provides constants and types for working with TAP messages,
4//! including security modes and message type identifiers.
5
6use base64::{engine::general_purpose, Engine};
7use serde::{Deserialize, Serialize};
8// Value is not used in this file
9
10/// Security mode for message packing and unpacking.
11///
12/// Defines the level of protection applied to messages:
13/// - `Plain`: No encryption or signing (insecure, only for testing)
14/// - `Signed`: Message is signed but not encrypted (integrity protected)
15/// - `AuthCrypt`: Message is authenticated and encrypted (confidentiality + integrity)
16/// - `Any`: Accept any security mode when unpacking (only used for receiving)
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum SecurityMode {
19    /// Plaintext - no encryption or signatures
20    Plain,
21    /// Signed - message is signed but not encrypted
22    Signed,
23    /// Authenticated and Encrypted - message is both signed and encrypted
24    AuthCrypt,
25    /// Any security mode - used for unpacking when any mode is acceptable
26    Any,
27}
28
29/// Message type identifiers used by the TAP Protocol
30/// These constant strings are used to identify different message types
31/// in the TAP protocol communications.
32/// Type identifier for Presentation messages
33pub const PRESENTATION_MESSAGE_TYPE: &str = "https://tap.rsvp/schema/1.0#Presentation";
34
35pub const DIDCOMM_SIGNED: &str = "application/didcomm-signed+json";
36pub const DIDCOMM_ENCRYPTED: &str = "application/didcomm-encrypted+json";
37
38// JWS-related types
39
40#[derive(Serialize, Deserialize, Debug)]
41pub struct Jws {
42    pub payload: String,
43    pub signatures: Vec<JwsSignature>,
44}
45
46#[derive(Serialize, Deserialize, Debug)]
47pub struct JwsSignature {
48    pub protected: String,
49    pub signature: String,
50}
51
52// Structure for decoded JWS protected field
53#[derive(Serialize, Deserialize, Debug, Clone)]
54pub struct JwsProtected {
55    #[serde(default = "default_didcomm_signed")]
56    pub typ: String,
57    pub alg: String,
58    pub kid: String,
59}
60
61// Helper function for JwsProtected typ default
62fn default_didcomm_signed() -> String {
63    DIDCOMM_SIGNED.to_string()
64}
65
66impl JwsSignature {
67    /// Extracts the kid (key identifier) from the protected header
68    pub fn get_kid(&self) -> Option<String> {
69        // Decode the protected header and extract kid
70        if let Ok(protected_bytes) = general_purpose::STANDARD.decode(&self.protected) {
71            if let Ok(protected) = serde_json::from_slice::<JwsProtected>(&protected_bytes) {
72                return Some(protected.kid);
73            }
74        }
75        None
76    }
77
78    /// Decodes and returns the protected header
79    pub fn get_protected_header(&self) -> Result<JwsProtected, Box<dyn std::error::Error>> {
80        let protected_bytes = general_purpose::STANDARD.decode(&self.protected)?;
81        let protected = serde_json::from_slice::<JwsProtected>(&protected_bytes)?;
82        Ok(protected)
83    }
84}
85// JWE-related types
86
87#[derive(Serialize, Deserialize, Debug)]
88pub struct Jwe {
89    pub ciphertext: String,
90    pub protected: String,
91    pub recipients: Vec<JweRecipient>,
92    pub tag: String,
93    pub iv: String,
94}
95
96#[derive(Serialize, Deserialize, Debug)]
97pub struct JweRecipient {
98    pub encrypted_key: String,
99    pub header: JweHeader,
100}
101
102#[derive(Serialize, Deserialize, Debug)]
103pub struct JweHeader {
104    pub kid: String,
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub sender_kid: Option<String>,
107}
108
109// Structure for decoded JWE protected field
110#[derive(Serialize, Deserialize, Debug)]
111pub struct JweProtected {
112    pub epk: EphemeralPublicKey,
113    pub apv: String,
114    #[serde(default = "default_didcomm_encrypted")]
115    pub typ: String,
116    pub enc: String,
117    pub alg: String,
118}
119
120// Helper function for JweProtected typ default
121fn default_didcomm_encrypted() -> String {
122    DIDCOMM_ENCRYPTED.to_string()
123}
124
125// Enum to handle different ephemeral public key types
126#[derive(Serialize, Deserialize, Debug)]
127#[serde(tag = "kty")]
128pub enum EphemeralPublicKey {
129    #[serde(rename = "EC")]
130    Ec { crv: String, x: String, y: String },
131    #[serde(rename = "OKP")]
132    Okp { crv: String, x: String },
133}