Skip to main content

p2panda_encryption/traits/
message.rs

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