1use xso::{text::Base64, AsXml, FromXml};
8
9use crate::message::MessagePayload;
10use crate::ns;
11use crate::pubsub::PubSubPayload;
12
13#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
15#[xml(namespace = ns::LEGACY_OMEMO, name = "device")]
16pub struct Device {
17 #[xml(attribute)]
19 pub id: u32,
20}
21
22#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
25#[xml(namespace = ns::LEGACY_OMEMO, name = "list")]
26pub struct DeviceList {
27 #[xml(child(n = ..))]
29 pub devices: Vec<Device>,
30}
31
32impl PubSubPayload for DeviceList {}
33
34#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
37#[xml(namespace = ns::LEGACY_OMEMO, name = "signedPreKeyPublic")]
38pub struct SignedPreKeyPublic {
39 #[xml(attribute(default, name = "signedPreKeyId"))]
41 pub signed_pre_key_id: Option<u32>,
42
43 #[xml(text = Base64)]
45 pub data: Vec<u8>,
46}
47
48#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
51#[xml(namespace = ns::LEGACY_OMEMO, name = "signedPreKeySignature")]
52pub struct SignedPreKeySignature {
53 #[xml(text = Base64)]
55 pub data: Vec<u8>,
56}
57
58#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
60#[xml(namespace = ns::LEGACY_OMEMO, name = "identityKey")]
61pub struct IdentityKey {
62 #[xml(text = Base64)]
64 pub data: Vec<u8>,
65}
66
67#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
70#[xml(namespace = ns::LEGACY_OMEMO, name = "prekeys")]
71pub struct Prekeys {
72 #[xml(child(n = ..))]
74 pub keys: Vec<PreKeyPublic>,
75}
76
77#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
80#[xml(namespace = ns::LEGACY_OMEMO, name = "preKeyPublic")]
81pub struct PreKeyPublic {
82 #[xml(attribute = "preKeyId")]
84 pub pre_key_id: u32,
85
86 #[xml(text = Base64)]
88 pub data: Vec<u8>,
89}
90
91#[derive(FromXml, AsXml, Debug, PartialEq, Clone)]
95#[xml(namespace = ns::LEGACY_OMEMO, name = "bundle")]
96pub struct Bundle {
97 #[xml(child(default))]
99 pub signed_pre_key_public: Option<SignedPreKeyPublic>,
100
101 #[xml(child(default))]
103 pub signed_pre_key_signature: Option<SignedPreKeySignature>,
104
105 #[xml(child(default))]
107 pub identity_key: Option<IdentityKey>,
108
109 #[xml(child(default))]
111 pub prekeys: Option<Prekeys>,
112}
113
114impl PubSubPayload for Bundle {}
115
116#[derive(FromXml, AsXml, Debug, PartialEq, Clone)]
118#[xml(namespace = ns::LEGACY_OMEMO, name = "header")]
119pub struct Header {
120 #[xml(attribute)]
122 pub sid: u32,
123
124 #[xml(child(n = ..))]
127 pub keys: Vec<Key>,
128
129 #[xml(child)]
131 pub iv: IV,
132}
133
134#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
136#[xml(namespace = ns::LEGACY_OMEMO, name = "iv")]
137pub struct IV {
138 #[xml(text = Base64)]
140 pub data: Vec<u8>,
141}
142
143#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
145#[xml(namespace = ns::LEGACY_OMEMO, name = "key")]
146pub struct Key {
147 #[xml(attribute)]
149 pub rid: u32,
150
151 #[xml(attribute(default))]
154 pub prekey: bool,
155
156 #[xml(text = Base64)]
160 pub data: Vec<u8>,
161}
162
163#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
165#[xml(namespace = ns::LEGACY_OMEMO, name = "payload")]
166pub struct Payload {
167 #[xml(text = Base64)]
169 pub data: Vec<u8>,
170}
171
172#[derive(FromXml, AsXml, Debug, PartialEq, Clone)]
175#[xml(namespace = ns::LEGACY_OMEMO, name = "encrypted")]
176pub struct Encrypted {
177 #[xml(child)]
179 pub header: Header,
180
181 #[xml(child(default))]
183 pub payload: Option<Payload>,
184}
185
186impl MessagePayload for Encrypted {}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191 use minidom::Element;
192
193 #[test]
194 fn parse_bundle() {
195 let elem: Element = r#"<bundle xmlns="eu.siacs.conversations.axolotl">
196 <signedPreKeyPublic signedPreKeyId="1">BYAbACA15bPn95p7RGC2XbgQyly8aRKS4BaJ+hD8Ybhe</signedPreKeyPublic>
197 <signedPreKeySignature>sIJVNDZi/NgFsry4OBdM+adyGttLEXbUh/h/5dVOZveMgyVoIdgwBUzq8Wgd2xYTQMioNzwYebTX+9p0h9eujA==</signedPreKeySignature>
198 <identityKey>BQFd2p/Oq97vAAdLKA09DlcSg0x1xWn260p1jaeyIhAZ</identityKey>
199 <prekeys>
200 <preKeyPublic preKeyId="1">BbjHsF5ndtNV8ToRcJTYSNGePgAWsFGkSL6OG7B7LXRe</preKeyPublic>
201 <preKeyPublic preKeyId="2">BeWHsbBNx1uer1ia/nW/6tn/OlqHll9itjjUTIvV39x7</preKeyPublic>
202 <preKeyPublic preKeyId="3">BeVr5xPmNErkwK3ocPmv0Nohy3C4PKQBnxMuOqiXotJY</preKeyPublic>
203 </prekeys>
204</bundle>
205 "#.parse().unwrap();
206 let bundle: Bundle = elem.try_into().unwrap();
207 let bundle2 = Bundle {
208 signed_pre_key_public: Some(SignedPreKeyPublic {
209 signed_pre_key_id: Some(1),
210 data: vec![
211 5, 128, 27, 0, 32, 53, 229, 179, 231, 247, 154, 123, 68, 96, 182, 93, 184, 16,
212 202, 92, 188, 105, 18, 146, 224, 22, 137, 250, 16, 252, 97, 184, 94,
213 ],
214 }),
215 signed_pre_key_signature: Some(SignedPreKeySignature {
216 data: vec![
217 176, 130, 85, 52, 54, 98, 252, 216, 5, 178, 188, 184, 56, 23, 76, 249, 167,
218 114, 26, 219, 75, 17, 118, 212, 135, 248, 127, 229, 213, 78, 102, 247, 140,
219 131, 37, 104, 33, 216, 48, 5, 76, 234, 241, 104, 29, 219, 22, 19, 64, 200, 168,
220 55, 60, 24, 121, 180, 215, 251, 218, 116, 135, 215, 174, 140,
221 ],
222 }),
223 identity_key: Some(IdentityKey {
224 data: vec![
225 5, 1, 93, 218, 159, 206, 171, 222, 239, 0, 7, 75, 40, 13, 61, 14, 87, 18, 131,
226 76, 117, 197, 105, 246, 235, 74, 117, 141, 167, 178, 34, 16, 25,
227 ],
228 }),
229 prekeys: Some(Prekeys {
230 keys: vec![
231 PreKeyPublic {
232 pre_key_id: 1,
233 data: vec![
234 5, 184, 199, 176, 94, 103, 118, 211, 85, 241, 58, 17, 112, 148, 216,
235 72, 209, 158, 62, 0, 22, 176, 81, 164, 72, 190, 142, 27, 176, 123, 45,
236 116, 94,
237 ],
238 },
239 PreKeyPublic {
240 pre_key_id: 2,
241 data: vec![
242 5, 229, 135, 177, 176, 77, 199, 91, 158, 175, 88, 154, 254, 117, 191,
243 234, 217, 255, 58, 90, 135, 150, 95, 98, 182, 56, 212, 76, 139, 213,
244 223, 220, 123,
245 ],
246 },
247 PreKeyPublic {
248 pre_key_id: 3,
249 data: vec![
250 5, 229, 107, 231, 19, 230, 52, 74, 228, 192, 173, 232, 112, 249, 175,
251 208, 218, 33, 203, 112, 184, 60, 164, 1, 159, 19, 46, 58, 168, 151,
252 162, 210, 88,
253 ],
254 },
255 ],
256 }),
257 };
258 assert_eq!(bundle, bundle2);
259 }
260 #[test]
261 fn parse_device_list() {
262 let elem: Element = r#"<list xmlns="eu.siacs.conversations.axolotl">
263 <device id="1164059891" />
264 <device id="26052318" />
265 <device id="564866972" />
266</list>
267 "#
268 .parse()
269 .unwrap();
270 let list: DeviceList = elem.try_into().unwrap();
271 let list2 = DeviceList {
272 devices: vec![
273 Device { id: 1164059891 },
274 Device { id: 26052318 },
275 Device { id: 564866972 },
276 ],
277 };
278 assert_eq!(list, list2);
279 }
280 #[test]
281 fn parse_encrypted() {
282 let elem: Element = r#"<encrypted xmlns="eu.siacs.conversations.axolotl">
283 <header sid="564866972">
284 <key prekey="true" rid="1236">Mwjp9AESIQVylscLPpj/HlowaTiIsaBj73HCVEllXpVTtMG9EYwRexohBQFd2p/Oq97vAAdLKA09DlcSg0x1xWn260p1jaeyIhAZImIzCiEFhaQ4I+DuQgo6vCLCjHu4uewDZmWHuBl8uJw1IkyZxhUQABgAIjCoEVgVThWlaIlnN3V5Bg1hQX7OD1cvstLD5lH3zZMadL3KeONELESlBbeKmNgcYC/e3HZnbgWzBiic36yNAjAW</key>
285 <key rid="26052318">MwohBTV6dpumL1OxA9MdIFmu2E19+cIWDHWYfhdubvo0hmh6EAAYHCIwNc9/59eeYi8pVZQhMJJMVkKUkFP/yrTfG3o1lfpHGseCqb/JTgtDytQPiYrTpHl2V/mdsM6IPig=</key>
286 <key rid="1164059891">MwohBVnhz9pvEj1s1waEHuk5qpQqhUrpavycFz0hq/KYwI8oEAAYCSIwedEGN6MidxyvaPI8zorLcpG0Y7e7ecGkkd5vdDrL7Qt1tXaHb0iDyE/rZZHpFiNN38Izfp5vHv4=</key>
287 <iv>SY/SCGPt0CnA2odB</iv>
288 </header>
289 <payload>Vas=</payload>
290</encrypted>
291 "#.parse().unwrap();
292 let encrypted: Encrypted = elem.try_into().unwrap();
293 let encrypted2 = Encrypted {
294 header: Header {
295 sid: 564866972,
296 keys: vec![
297 Key {
298 rid: 1236,
299 prekey: true,
300 data: vec![
301 51, 8, 233, 244, 1, 18, 33, 5, 114, 150, 199, 11, 62, 152, 255, 30, 90,
302 48, 105, 56, 136, 177, 160, 99, 239, 113, 194, 84, 73, 101, 94, 149,
303 83, 180, 193, 189, 17, 140, 17, 123, 26, 33, 5, 1, 93, 218, 159, 206,
304 171, 222, 239, 0, 7, 75, 40, 13, 61, 14, 87, 18, 131, 76, 117, 197,
305 105, 246, 235, 74, 117, 141, 167, 178, 34, 16, 25, 34, 98, 51, 10, 33,
306 5, 133, 164, 56, 35, 224, 238, 66, 10, 58, 188, 34, 194, 140, 123, 184,
307 185, 236, 3, 102, 101, 135, 184, 25, 124, 184, 156, 53, 34, 76, 153,
308 198, 21, 16, 0, 24, 0, 34, 48, 168, 17, 88, 21, 78, 21, 165, 104, 137,
309 103, 55, 117, 121, 6, 13, 97, 65, 126, 206, 15, 87, 47, 178, 210, 195,
310 230, 81, 247, 205, 147, 26, 116, 189, 202, 120, 227, 68, 44, 68, 165,
311 5, 183, 138, 152, 216, 28, 96, 47, 222, 220, 118, 103, 110, 5, 179, 6,
312 40, 156, 223, 172, 141, 2, 48, 22,
313 ],
314 },
315 Key {
316 rid: 26052318,
317 prekey: false,
318 data: vec![
319 51, 10, 33, 5, 53, 122, 118, 155, 166, 47, 83, 177, 3, 211, 29, 32, 89,
320 174, 216, 77, 125, 249, 194, 22, 12, 117, 152, 126, 23, 110, 110, 250,
321 52, 134, 104, 122, 16, 0, 24, 28, 34, 48, 53, 207, 127, 231, 215, 158,
322 98, 47, 41, 85, 148, 33, 48, 146, 76, 86, 66, 148, 144, 83, 255, 202,
323 180, 223, 27, 122, 53, 149, 250, 71, 26, 199, 130, 169, 191, 201, 78,
324 11, 67, 202, 212, 15, 137, 138, 211, 164, 121, 118, 87, 249, 157, 176,
325 206, 136, 62, 40,
326 ],
327 },
328 Key {
329 rid: 1164059891,
330 prekey: false,
331 data: vec![
332 51, 10, 33, 5, 89, 225, 207, 218, 111, 18, 61, 108, 215, 6, 132, 30,
333 233, 57, 170, 148, 42, 133, 74, 233, 106, 252, 156, 23, 61, 33, 171,
334 242, 152, 192, 143, 40, 16, 0, 24, 9, 34, 48, 121, 209, 6, 55, 163, 34,
335 119, 28, 175, 104, 242, 60, 206, 138, 203, 114, 145, 180, 99, 183, 187,
336 121, 193, 164, 145, 222, 111, 116, 58, 203, 237, 11, 117, 181, 118,
337 135, 111, 72, 131, 200, 79, 235, 101, 145, 233, 22, 35, 77, 223, 194,
338 51, 126, 158, 111, 30, 254,
339 ],
340 },
341 ],
342 iv: IV {
343 data: vec![73, 143, 210, 8, 99, 237, 208, 41, 192, 218, 135, 65],
344 },
345 },
346 payload: Some(Payload {
347 data: vec![85, 171],
348 }),
349 };
350 assert_eq!(encrypted, encrypted2);
351 }
352}