vodozemac/olm/session/
message_key.rs1use std::fmt::Debug;
16
17use serde::{Deserialize, Serialize};
18use zeroize::Zeroize;
19
20use super::{ratchet::RatchetPublicKey, DecryptionError};
21use crate::{
22 cipher::{Cipher, Mac},
23 olm::messages::Message,
24};
25
26pub struct MessageKey {
30 key: Box<[u8; 32]>,
31 ratchet_key: RatchetPublicKey,
32 index: u64,
33}
34
35impl Drop for MessageKey {
36 fn drop(&mut self) {
37 self.key.zeroize()
38 }
39}
40
41#[derive(Serialize, Deserialize, Clone)]
42pub(super) struct RemoteMessageKey {
43 pub key: Box<[u8; 32]>,
44 pub index: u64,
45}
46
47impl Debug for RemoteMessageKey {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 let Self { key: _, index } = self;
50
51 f.debug_struct("RemoteMessageKey").field("index", index).finish()
52 }
53}
54
55impl Drop for RemoteMessageKey {
56 fn drop(&mut self) {
57 self.key.zeroize()
58 }
59}
60
61impl MessageKey {
62 pub const fn new(key: Box<[u8; 32]>, ratchet_key: RatchetPublicKey, index: u64) -> Self {
68 Self { key, ratchet_key, index }
69 }
70
71 pub fn encrypt(self, plaintext: &[u8]) -> Message {
78 let cipher = Cipher::new(&self.key);
79
80 let ciphertext = cipher.encrypt(plaintext);
81
82 let mut message = Message::new(*self.ratchet_key.as_ref(), self.index, ciphertext);
83
84 let mac = cipher.mac(&message.to_mac_bytes());
85 message.set_mac(mac);
86
87 message
88 }
89
90 pub fn encrypt_truncated_mac(self, plaintext: &[u8]) -> Message {
96 let cipher = Cipher::new(&self.key);
97
98 let ciphertext = cipher.encrypt(plaintext);
99
100 let mut message =
101 Message::new_truncated_mac(*self.ratchet_key.as_ref(), self.index, ciphertext);
102
103 let mac = cipher.mac(&message.to_mac_bytes());
104 message.set_mac(mac);
105
106 message
107 }
108
109 #[cfg(feature = "low-level-api")]
111 pub fn key(&self) -> &[u8; 32] {
112 self.key.as_ref()
113 }
114
115 #[cfg(feature = "low-level-api")]
117 pub const fn ratchet_key(&self) -> RatchetPublicKey {
118 self.ratchet_key
119 }
120
121 #[cfg(feature = "low-level-api")]
123 pub const fn index(&self) -> u64 {
124 self.index
125 }
126}
127
128impl RemoteMessageKey {
129 pub const fn new(key: Box<[u8; 32]>, index: u64) -> Self {
130 Self { key, index }
131 }
132
133 pub const fn chain_index(&self) -> u64 {
134 self.index
135 }
136
137 pub fn decrypt_truncated_mac(&self, message: &Message) -> Result<Vec<u8>, DecryptionError> {
138 let cipher = Cipher::new(&self.key);
139
140 if let crate::cipher::MessageMac::Truncated(m) = &message.mac {
141 cipher.verify_truncated_mac(&message.to_mac_bytes(), m)?;
142 Ok(cipher.decrypt(&message.ciphertext)?)
143 } else {
144 Err(DecryptionError::InvalidMACLength(Mac::TRUNCATED_LEN, Mac::LENGTH))
145 }
146 }
147
148 pub fn decrypt(&self, message: &Message) -> Result<Vec<u8>, DecryptionError> {
149 let cipher = Cipher::new(&self.key);
150
151 if let crate::cipher::MessageMac::Full(m) = &message.mac {
152 cipher.verify_mac(&message.to_mac_bytes(), m)?;
153 Ok(cipher.decrypt(&message.ciphertext)?)
154 } else {
155 Err(DecryptionError::InvalidMACLength(Mac::LENGTH, Mac::TRUNCATED_LEN))
156 }
157 }
158}
159
160#[cfg(test)]
161#[cfg(feature = "low-level-api")]
162mod test {
163 use super::MessageKey;
164 use crate::olm::RatchetPublicKey;
165
166 #[test]
167 fn low_level_getters() {
168 let key = b"11111111111111111111111111111111";
169 let ratchet_key = RatchetPublicKey::from(*b"22222222222222222222222222222222");
170 let index: u64 = 3;
171 let message_key = MessageKey::new(Box::new(*key), ratchet_key, index);
172 assert_eq!(message_key.key(), key);
173 assert_eq!(message_key.ratchet_key(), ratchet_key);
174 assert_eq!(message_key.index(), index);
175 }
176}