p2panda_encryption/traits/
message.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use std::fmt::Display;
4
5use crate::crypto::xchacha20::XAeadNonce;
6#[cfg(any(test, feature = "data_scheme"))]
7use crate::data_scheme::{self, GroupSecretId};
8#[cfg(any(test, feature = "message_scheme"))]
9use crate::message_scheme::{self, Generation};
10#[cfg(any(test, feature = "message_scheme"))]
11use crate::traits::AckedGroupMembership;
12#[cfg(any(test, feature = "data_scheme"))]
13use crate::traits::GroupMembership;
14
15/// Interface to express required information from messages following the "data encryption"
16/// protocol for groups.
17///
18/// Applications implementing these traits should authenticate the original sender of each message.
19///
20/// Messages, except of the direct ones, need to be broadcast to the whole group.
21#[cfg(any(test, feature = "data_scheme"))]
22pub trait GroupMessage<ID, OP, DGM>
23where
24    DGM: GroupMembership<ID, OP>,
25{
26    /// Unique identifier of this message.
27    fn id(&self) -> OP;
28
29    /// Unique identifier of the sender of this message.
30    fn sender(&self) -> ID;
31
32    /// Returns content of either a control- or application message.
33    fn content(&self) -> GroupMessageContent<ID>;
34
35    /// Returns optional list of direct messages.
36    fn direct_messages(&self) -> Vec<data_scheme::DirectMessage<ID, OP, DGM>>;
37}
38
39#[cfg(any(test, feature = "data_scheme"))]
40#[derive(Debug)]
41pub enum GroupMessageContent<ID> {
42    /// Control message managing encryption group.
43    Control(data_scheme::ControlMessage<ID>),
44
45    /// Encrypted application payload indicating which AEAD key and nonce was used.
46    Application {
47        /// Identifier of the used AEAD key (group secret).
48        group_secret_id: GroupSecretId,
49
50        /// AEAD nonce.
51        nonce: XAeadNonce,
52
53        /// Payload encrypted with AEAD.
54        ciphertext: Vec<u8>,
55    },
56}
57
58#[cfg(any(test, feature = "data_scheme"))]
59impl<ID> Display for GroupMessageContent<ID> {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        write!(
62            f,
63            "{}",
64            match self {
65                Self::Control(control_message) => control_message.to_string(),
66                Self::Application {
67                    group_secret_id, ..
68                } => format!("application @{}", hex::encode(group_secret_id)),
69            }
70        )
71    }
72}
73
74/// Interface to express required information from messages following the "message encryption"
75/// protocol for groups.
76///
77/// Applications implementing these traits should authenticate the original sender of each message.
78///
79/// Messages, except for the direct ones, need to be broadcast to the whole group.
80#[cfg(any(test, feature = "message_scheme"))]
81pub trait ForwardSecureGroupMessage<ID, OP, DGM>
82where
83    DGM: AckedGroupMembership<ID, OP>,
84{
85    /// Unique identifier of this message.
86    fn id(&self) -> OP;
87
88    /// Unique identifier of the sender of this message.
89    fn sender(&self) -> ID;
90
91    /// Returns data required to manage group encryption and receive decrypted application messages.
92    fn content(&self) -> ForwardSecureMessageContent<ID, OP>;
93
94    /// Returns optional list of direct messages.
95    ///
96    /// Direct messages do not need to be encoded as part of one broadcast message. Applications
97    /// can also decide to keep control messages and direct messages detached and use
98    /// `ForwardSecureMessage` as a way to express which control message belonged to this set of
99    /// direct messages.
100    fn direct_messages(&self) -> Vec<message_scheme::DirectMessage<ID, OP, DGM>>;
101}
102
103#[cfg(any(test, feature = "message_scheme"))]
104#[derive(Debug)]
105pub enum ForwardSecureMessageContent<ID, OP> {
106    /// Control message managing messaging encryption group.
107    Control(message_scheme::ControlMessage<ID, OP>),
108
109    /// Encrypted application message payload indicating which ratchet generation was used.
110    Application {
111        ciphertext: Vec<u8>,
112        generation: Generation,
113    },
114}
115
116#[cfg(any(test, feature = "message_scheme"))]
117impl<ID, OP> Display for ForwardSecureMessageContent<ID, OP> {
118    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119        write!(
120            f,
121            "{}",
122            match self {
123                Self::Control(control_message) => control_message.to_string(),
124                Self::Application { generation, .. } => format!("application @{generation}"),
125            }
126        )
127    }
128}