1// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7use crate::data_forms::DataForm;
8use crate::disco::{DiscoInfoQuery, DiscoInfoResult, Feature, Identity};
9use crate::hashes::{Algo, Hash};
10use crate::ns;
11use crate::presence::PresencePayload;
12use crate::util::error::Error;
13use blake2::Blake2bVar;
14use digest::{Digest, Update, VariableOutput};
15use sha2::{Sha256, Sha512};
16use sha3::{Sha3_256, Sha3_512};
17
18generate_element!(
19 /// Represents a set of capability hashes, all of them must correspond to
20 /// the same input [disco#info](../disco/struct.DiscoInfoResult.html),
21 /// using different [algorithms](../hashes/enum.Algo.html).
22 ECaps2, "c", ECAPS2,
23 children: [
24 /// Hashes of the [disco#info](../disco/struct.DiscoInfoResult.html).
25 hashes: Vec<Hash> = ("hash", HASHES) => Hash
26 ]
27);
28
29impl PresencePayload for ECaps2 {}
30
31impl ECaps2 {
32 /// Create an ECaps2 element from a list of hashes.
33 pub fn new(hashes: Vec<Hash>) -> ECaps2 {
34 ECaps2 { hashes }
35 }
36}
37
38fn compute_item(field: &str) -> Vec<u8> {
39 let mut bytes = field.as_bytes().to_vec();
40 bytes.push(0x1f);
41 bytes
42}
43
44fn compute_items<T, F: Fn(&T) -> Vec<u8>>(things: &[T], separator: u8, encode: F) -> Vec<u8> {
45 let mut string: Vec<u8> = vec![];
46 let mut accumulator: Vec<Vec<u8>> = vec![];
47 for thing in things {
48 let bytes = encode(thing);
49 accumulator.push(bytes);
50 }
51 // This works using the expected i;octet collation.
52 accumulator.sort();
53 for mut bytes in accumulator {
54 string.append(&mut bytes);
55 }
56 string.push(separator);
57 string
58}
59
60fn compute_features(features: &[Feature]) -> Vec<u8> {
61 compute_items(features, 0x1c, |feature| compute_item(&feature.var))
62}
63
64fn compute_identities(identities: &[Identity]) -> Vec<u8> {
65 compute_items(identities, 0x1c, |identity| {
66 let mut bytes = compute_item(&identity.category);
67 bytes.append(&mut compute_item(&identity.type_));
68 bytes.append(&mut compute_item(
69 &identity.lang.clone().unwrap_or_default(),
70 ));
71 bytes.append(&mut compute_item(
72 &identity.name.clone().unwrap_or_default(),
73 ));
74 bytes.push(0x1e);
75 bytes
76 })
77}
78
79fn compute_extensions(extensions: &[DataForm]) -> Result<Vec<u8>, Error> {
80 for extension in extensions {
81 if extension.form_type.is_none() {
82 return Err(Error::ParseError("Missing FORM_TYPE in extension."));
83 }
84 }
85 Ok(compute_items(extensions, 0x1c, |extension| {
86 let mut bytes = compute_item("FORM_TYPE");
87 bytes.append(&mut compute_item(
88 if let Some(ref form_type) = extension.form_type {
89 form_type
90 } else {
91 unreachable!()
92 },
93 ));
94 bytes.push(0x1e);
95 bytes.append(&mut compute_items(&extension.fields, 0x1d, |field| {
96 let mut bytes = compute_item(&field.var);
97 bytes.append(&mut compute_items(&field.values, 0x1e, |value| {
98 compute_item(value)
99 }));
100 bytes
101 }));
102 bytes
103 }))
104}
105
106/// Applies the [algorithm from
107/// XEP-0390](https://xmpp.org/extensions/xep-0390.html#algorithm-input) on a
108/// [disco#info query element](../disco/struct.DiscoInfoResult.html).
109pub fn compute_disco(disco: &DiscoInfoResult) -> Result<Vec<u8>, Error> {
110 let features_string = compute_features(&disco.features);
111 let identities_string = compute_identities(&disco.identities);
112 let extensions_string = compute_extensions(&disco.extensions)?;
113
114 let mut final_string = vec![];
115 final_string.extend(features_string);
116 final_string.extend(identities_string);
117 final_string.extend(extensions_string);
118 Ok(final_string)
119}
120
121fn get_hash_vec(hash: &[u8]) -> Vec<u8> {
122 let mut vec = Vec::with_capacity(hash.len());
123 vec.extend_from_slice(hash);
124 vec
125}
126
127/// Hashes the result of [compute_disco()] with one of the supported [hash
128/// algorithms](../hashes/enum.Algo.html).
129pub fn hash_ecaps2(data: &[u8], algo: Algo) -> Result<Hash, Error> {
130 Ok(Hash {
131 hash: match algo {
132 Algo::Sha_256 => {
133 let hash = Sha256::digest(data);
134 get_hash_vec(hash.as_slice())
135 }
136 Algo::Sha_512 => {
137 let hash = Sha512::digest(data);
138 get_hash_vec(hash.as_slice())
139 }
140 Algo::Sha3_256 => {
141 let hash = Sha3_256::digest(data);
142 get_hash_vec(hash.as_slice())
143 }
144 Algo::Sha3_512 => {
145 let hash = Sha3_512::digest(data);
146 get_hash_vec(hash.as_slice())
147 }
148 Algo::Blake2b_256 => {
149 let mut hasher = Blake2bVar::new(32).unwrap();
150 hasher.update(data);
151 let mut vec = vec![0u8; 32];
152 hasher.finalize_variable(&mut vec).unwrap();
153 vec
154 }
155 Algo::Blake2b_512 => {
156 let mut hasher = Blake2bVar::new(64).unwrap();
157 hasher.update(data);
158 let mut vec = vec![0u8; 64];
159 hasher.finalize_variable(&mut vec).unwrap();
160 vec
161 }
162 Algo::Sha_1 => return Err(Error::ParseError("Disabled algorithm sha-1: unsafe.")),
163 Algo::Unknown(_algo) => return Err(Error::ParseError("Unknown algorithm in ecaps2.")),
164 },
165 algo,
166 })
167}
168
169/// Helper function to create the query for the disco#info corresponding to an
170/// ecaps2 hash.
171pub fn query_ecaps2(hash: Hash) -> DiscoInfoQuery {
172 DiscoInfoQuery {
173 node: Some(format!(
174 "{}#{}.{}",
175 ns::ECAPS2,
176 String::from(hash.algo),
177 base64::encode(&hash.hash)
178 )),
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185 use crate::util::error::Error;
186 use crate::Element;
187 use std::convert::TryFrom;
188
189 #[cfg(target_pointer_width = "32")]
190 #[test]
191 fn test_size() {
192 assert_size!(ECaps2, 12);
193 }
194
195 #[cfg(target_pointer_width = "64")]
196 #[test]
197 fn test_size() {
198 assert_size!(ECaps2, 24);
199 }
200
201 #[test]
202 fn test_parse() {
203 let elem: Element = "<c xmlns='urn:xmpp:caps'><hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=</hash><hash xmlns='urn:xmpp:hashes:2' algo='sha3-256'>+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=</hash></c>".parse().unwrap();
204 let ecaps2 = ECaps2::try_from(elem).unwrap();
205 assert_eq!(ecaps2.hashes.len(), 2);
206 assert_eq!(ecaps2.hashes[0].algo, Algo::Sha_256);
207 assert_eq!(
208 ecaps2.hashes[0].hash,
209 base64::decode("K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=").unwrap()
210 );
211 assert_eq!(ecaps2.hashes[1].algo, Algo::Sha3_256);
212 assert_eq!(
213 ecaps2.hashes[1].hash,
214 base64::decode("+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=").unwrap()
215 );
216 }
217
218 #[test]
219 fn test_invalid_child() {
220 let elem: Element = "<c xmlns='urn:xmpp:caps'><hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=</hash><hash xmlns='urn:xmpp:hashes:1' algo='sha3-256'>+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=</hash></c>".parse().unwrap();
221 let error = ECaps2::try_from(elem).unwrap_err();
222 let message = match error {
223 Error::ParseError(string) => string,
224 _ => panic!(),
225 };
226 assert_eq!(message, "Unknown child in c element.");
227 }
228
229 #[test]
230 fn test_simple() {
231 let elem: Element = "<query xmlns='http://jabber.org/protocol/disco#info'><identity category='client' type='pc'/><feature var='http://jabber.org/protocol/disco#info'/></query>".parse().unwrap();
232 let disco = DiscoInfoResult::try_from(elem).unwrap();
233 let ecaps2 = compute_disco(&disco).unwrap();
234 assert_eq!(ecaps2.len(), 54);
235 }
236
237 #[test]
238 fn test_xep_ex1() {
239 let elem: Element = r#"
240<query xmlns="http://jabber.org/protocol/disco#info">
241 <identity category="client" name="BombusMod" type="mobile"/>
242 <feature var="http://jabber.org/protocol/si"/>
243 <feature var="http://jabber.org/protocol/bytestreams"/>
244 <feature var="http://jabber.org/protocol/chatstates"/>
245 <feature var="http://jabber.org/protocol/disco#info"/>
246 <feature var="http://jabber.org/protocol/disco#items"/>
247 <feature var="urn:xmpp:ping"/>
248 <feature var="jabber:iq:time"/>
249 <feature var="jabber:iq:privacy"/>
250 <feature var="jabber:iq:version"/>
251 <feature var="http://jabber.org/protocol/rosterx"/>
252 <feature var="urn:xmpp:time"/>
253 <feature var="jabber:x:oob"/>
254 <feature var="http://jabber.org/protocol/ibb"/>
255 <feature var="http://jabber.org/protocol/si/profile/file-transfer"/>
256 <feature var="urn:xmpp:receipts"/>
257 <feature var="jabber:iq:roster"/>
258 <feature var="jabber:iq:last"/>
259</query>
260"#
261 .parse()
262 .unwrap();
263 let expected = vec![
264 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112,
265 114, 111, 116, 111, 99, 111, 108, 47, 98, 121, 116, 101, 115, 116, 114, 101, 97, 109,
266 115, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103,
267 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 99, 104, 97, 116, 115, 116, 97, 116,
268 101, 115, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114,
269 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 100, 105, 115, 99, 111, 35, 105,
270 110, 102, 111, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111,
271 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 100, 105, 115, 99, 111, 35,
272 105, 116, 101, 109, 115, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114,
273 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 105, 98, 98, 31, 104,
274 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
275 111, 116, 111, 99, 111, 108, 47, 114, 111, 115, 116, 101, 114, 120, 31, 104, 116, 116,
276 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116,
277 111, 99, 111, 108, 47, 115, 105, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98,
278 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 115, 105,
279 47, 112, 114, 111, 102, 105, 108, 101, 47, 102, 105, 108, 101, 45, 116, 114, 97, 110,
280 115, 102, 101, 114, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 108, 97, 115, 116,
281 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 112, 114, 105, 118, 97, 99, 121, 31,
282 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 114, 111, 115, 116, 101, 114, 31, 106, 97,
283 98, 98, 101, 114, 58, 105, 113, 58, 116, 105, 109, 101, 31, 106, 97, 98, 98, 101, 114,
284 58, 105, 113, 58, 118, 101, 114, 115, 105, 111, 110, 31, 106, 97, 98, 98, 101, 114, 58,
285 120, 58, 111, 111, 98, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58, 112, 105, 110,
286 103, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58, 114, 101, 99, 101, 105, 112, 116,
287 115, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58, 116, 105, 109, 101, 31, 28, 99,
288 108, 105, 101, 110, 116, 31, 109, 111, 98, 105, 108, 101, 31, 31, 66, 111, 109, 98,
289 117, 115, 77, 111, 100, 31, 30, 28, 28,
290 ];
291 let disco = DiscoInfoResult::try_from(elem).unwrap();
292 let ecaps2 = compute_disco(&disco).unwrap();
293 assert_eq!(ecaps2.len(), 0x1d9);
294 assert_eq!(ecaps2, expected);
295
296 let sha_256 = hash_ecaps2(&ecaps2, Algo::Sha_256).unwrap();
297 assert_eq!(
298 sha_256.hash,
299 base64::decode("kzBZbkqJ3ADrj7v08reD1qcWUwNGHaidNUgD7nHpiw8=").unwrap()
300 );
301 let sha3_256 = hash_ecaps2(&ecaps2, Algo::Sha3_256).unwrap();
302 assert_eq!(
303 sha3_256.hash,
304 base64::decode("79mdYAfU9rEdTOcWDO7UEAt6E56SUzk/g6TnqUeuD9Q=").unwrap()
305 );
306 }
307
308 #[test]
309 fn test_xep_ex2() {
310 let elem: Element = r#"
311<query xmlns="http://jabber.org/protocol/disco#info">
312 <identity category="client" name="Tkabber" type="pc" xml:lang="en"/>
313 <identity category="client" name="Ткаббер" type="pc" xml:lang="ru"/>
314 <feature var="games:board"/>
315 <feature var="http://jabber.org/protocol/activity"/>
316 <feature var="http://jabber.org/protocol/activity+notify"/>
317 <feature var="http://jabber.org/protocol/bytestreams"/>
318 <feature var="http://jabber.org/protocol/chatstates"/>
319 <feature var="http://jabber.org/protocol/commands"/>
320 <feature var="http://jabber.org/protocol/disco#info"/>
321 <feature var="http://jabber.org/protocol/disco#items"/>
322 <feature var="http://jabber.org/protocol/evil"/>
323 <feature var="http://jabber.org/protocol/feature-neg"/>
324 <feature var="http://jabber.org/protocol/geoloc"/>
325 <feature var="http://jabber.org/protocol/geoloc+notify"/>
326 <feature var="http://jabber.org/protocol/ibb"/>
327 <feature var="http://jabber.org/protocol/iqibb"/>
328 <feature var="http://jabber.org/protocol/mood"/>
329 <feature var="http://jabber.org/protocol/mood+notify"/>
330 <feature var="http://jabber.org/protocol/rosterx"/>
331 <feature var="http://jabber.org/protocol/si"/>
332 <feature var="http://jabber.org/protocol/si/profile/file-transfer"/>
333 <feature var="http://jabber.org/protocol/tune"/>
334 <feature var="http://www.facebook.com/xmpp/messages"/>
335 <feature var="http://www.xmpp.org/extensions/xep-0084.html#ns-metadata+notify"/>
336 <feature var="jabber:iq:avatar"/>
337 <feature var="jabber:iq:browse"/>
338 <feature var="jabber:iq:dtcp"/>
339 <feature var="jabber:iq:filexfer"/>
340 <feature var="jabber:iq:ibb"/>
341 <feature var="jabber:iq:inband"/>
342 <feature var="jabber:iq:jidlink"/>
343 <feature var="jabber:iq:last"/>
344 <feature var="jabber:iq:oob"/>
345 <feature var="jabber:iq:privacy"/>
346 <feature var="jabber:iq:roster"/>
347 <feature var="jabber:iq:time"/>
348 <feature var="jabber:iq:version"/>
349 <feature var="jabber:x:data"/>
350 <feature var="jabber:x:event"/>
351 <feature var="jabber:x:oob"/>
352 <feature var="urn:xmpp:avatar:metadata+notify"/>
353 <feature var="urn:xmpp:ping"/>
354 <feature var="urn:xmpp:receipts"/>
355 <feature var="urn:xmpp:time"/>
356 <x xmlns="jabber:x:data" type="result">
357 <field type="hidden" var="FORM_TYPE">
358 <value>urn:xmpp:dataforms:softwareinfo</value>
359 </field>
360 <field var="software">
361 <value>Tkabber</value>
362 </field>
363 <field var="software_version">
364 <value>0.11.1-svn-20111216-mod (Tcl/Tk 8.6b2)</value>
365 </field>
366 <field var="os">
367 <value>Windows</value>
368 </field>
369 <field var="os_version">
370 <value>XP</value>
371 </field>
372 </x>
373</query>
374"#
375 .parse()
376 .unwrap();
377 let expected = vec![
378 103, 97, 109, 101, 115, 58, 98, 111, 97, 114, 100, 31, 104, 116, 116, 112, 58, 47, 47,
379 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111,
380 108, 47, 97, 99, 116, 105, 118, 105, 116, 121, 31, 104, 116, 116, 112, 58, 47, 47, 106,
381 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47,
382 97, 99, 116, 105, 118, 105, 116, 121, 43, 110, 111, 116, 105, 102, 121, 31, 104, 116,
383 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111,
384 116, 111, 99, 111, 108, 47, 98, 121, 116, 101, 115, 116, 114, 101, 97, 109, 115, 31,
385 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112,
386 114, 111, 116, 111, 99, 111, 108, 47, 99, 104, 97, 116, 115, 116, 97, 116, 101, 115,
387 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47,
388 112, 114, 111, 116, 111, 99, 111, 108, 47, 99, 111, 109, 109, 97, 110, 100, 115, 31,
389 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112,
390 114, 111, 116, 111, 99, 111, 108, 47, 100, 105, 115, 99, 111, 35, 105, 110, 102, 111,
391 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47,
392 112, 114, 111, 116, 111, 99, 111, 108, 47, 100, 105, 115, 99, 111, 35, 105, 116, 101,
393 109, 115, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114,
394 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 101, 118, 105, 108, 31, 104, 116,
395 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111,
396 116, 111, 99, 111, 108, 47, 102, 101, 97, 116, 117, 114, 101, 45, 110, 101, 103, 31,
397 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112,
398 114, 111, 116, 111, 99, 111, 108, 47, 103, 101, 111, 108, 111, 99, 31, 104, 116, 116,
399 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116,
400 111, 99, 111, 108, 47, 103, 101, 111, 108, 111, 99, 43, 110, 111, 116, 105, 102, 121,
401 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47,
402 112, 114, 111, 116, 111, 99, 111, 108, 47, 105, 98, 98, 31, 104, 116, 116, 112, 58, 47,
403 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111,
404 108, 47, 105, 113, 105, 98, 98, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98,
405 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 109, 111,
406 111, 100, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114,
407 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 109, 111, 111, 100, 43, 110, 111,
408 116, 105, 102, 121, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46,
409 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 114, 111, 115, 116, 101,
410 114, 120, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114,
411 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 115, 105, 31, 104, 116, 116, 112,
412 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111,
413 99, 111, 108, 47, 115, 105, 47, 112, 114, 111, 102, 105, 108, 101, 47, 102, 105, 108,
414 101, 45, 116, 114, 97, 110, 115, 102, 101, 114, 31, 104, 116, 116, 112, 58, 47, 47,
415 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111,
416 108, 47, 116, 117, 110, 101, 31, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46,
417 102, 97, 99, 101, 98, 111, 111, 107, 46, 99, 111, 109, 47, 120, 109, 112, 112, 47, 109,
418 101, 115, 115, 97, 103, 101, 115, 31, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119,
419 46, 120, 109, 112, 112, 46, 111, 114, 103, 47, 101, 120, 116, 101, 110, 115, 105, 111,
420 110, 115, 47, 120, 101, 112, 45, 48, 48, 56, 52, 46, 104, 116, 109, 108, 35, 110, 115,
421 45, 109, 101, 116, 97, 100, 97, 116, 97, 43, 110, 111, 116, 105, 102, 121, 31, 106, 97,
422 98, 98, 101, 114, 58, 105, 113, 58, 97, 118, 97, 116, 97, 114, 31, 106, 97, 98, 98,
423 101, 114, 58, 105, 113, 58, 98, 114, 111, 119, 115, 101, 31, 106, 97, 98, 98, 101, 114,
424 58, 105, 113, 58, 100, 116, 99, 112, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58,
425 102, 105, 108, 101, 120, 102, 101, 114, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113,
426 58, 105, 98, 98, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 105, 110, 98, 97,
427 110, 100, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 106, 105, 100, 108, 105,
428 110, 107, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 108, 97, 115, 116, 31, 106,
429 97, 98, 98, 101, 114, 58, 105, 113, 58, 111, 111, 98, 31, 106, 97, 98, 98, 101, 114,
430 58, 105, 113, 58, 112, 114, 105, 118, 97, 99, 121, 31, 106, 97, 98, 98, 101, 114, 58,
431 105, 113, 58, 114, 111, 115, 116, 101, 114, 31, 106, 97, 98, 98, 101, 114, 58, 105,
432 113, 58, 116, 105, 109, 101, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 118, 101,
433 114, 115, 105, 111, 110, 31, 106, 97, 98, 98, 101, 114, 58, 120, 58, 100, 97, 116, 97,
434 31, 106, 97, 98, 98, 101, 114, 58, 120, 58, 101, 118, 101, 110, 116, 31, 106, 97, 98,
435 98, 101, 114, 58, 120, 58, 111, 111, 98, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58,
436 97, 118, 97, 116, 97, 114, 58, 109, 101, 116, 97, 100, 97, 116, 97, 43, 110, 111, 116,
437 105, 102, 121, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58, 112, 105, 110, 103, 31,
438 117, 114, 110, 58, 120, 109, 112, 112, 58, 114, 101, 99, 101, 105, 112, 116, 115, 31,
439 117, 114, 110, 58, 120, 109, 112, 112, 58, 116, 105, 109, 101, 31, 28, 99, 108, 105,
440 101, 110, 116, 31, 112, 99, 31, 101, 110, 31, 84, 107, 97, 98, 98, 101, 114, 31, 30,
441 99, 108, 105, 101, 110, 116, 31, 112, 99, 31, 114, 117, 31, 208, 162, 208, 186, 208,
442 176, 208, 177, 208, 177, 208, 181, 209, 128, 31, 30, 28, 70, 79, 82, 77, 95, 84, 89,
443 80, 69, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58, 100, 97, 116, 97, 102, 111, 114,
444 109, 115, 58, 115, 111, 102, 116, 119, 97, 114, 101, 105, 110, 102, 111, 31, 30, 111,
445 115, 31, 87, 105, 110, 100, 111, 119, 115, 31, 30, 111, 115, 95, 118, 101, 114, 115,
446 105, 111, 110, 31, 88, 80, 31, 30, 115, 111, 102, 116, 119, 97, 114, 101, 31, 84, 107,
447 97, 98, 98, 101, 114, 31, 30, 115, 111, 102, 116, 119, 97, 114, 101, 95, 118, 101, 114,
448 115, 105, 111, 110, 31, 48, 46, 49, 49, 46, 49, 45, 115, 118, 110, 45, 50, 48, 49, 49,
449 49, 50, 49, 54, 45, 109, 111, 100, 32, 40, 84, 99, 108, 47, 84, 107, 32, 56, 46, 54,
450 98, 50, 41, 31, 30, 29, 28,
451 ];
452 let disco = DiscoInfoResult::try_from(elem).unwrap();
453 let ecaps2 = compute_disco(&disco).unwrap();
454 assert_eq!(ecaps2.len(), 0x543);
455 assert_eq!(ecaps2, expected);
456
457 let sha_256 = hash_ecaps2(&ecaps2, Algo::Sha_256).unwrap();
458 assert_eq!(
459 sha_256.hash,
460 base64::decode("u79ZroNJbdSWhdSp311mddz44oHHPsEBntQ5b1jqBSY=").unwrap()
461 );
462 let sha3_256 = hash_ecaps2(&ecaps2, Algo::Sha3_256).unwrap();
463 assert_eq!(
464 sha3_256.hash,
465 base64::decode("XpUJzLAc93258sMECZ3FJpebkzuyNXDzRNwQog8eycg=").unwrap()
466 );
467 }
468
469 #[test]
470 fn test_blake2b_512() {
471 let hash = hash_ecaps2("abc".as_bytes(), Algo::Blake2b_512).unwrap();
472 let known_hash: Vec<u8> = vec![
473 0xBA, 0x80, 0xA5, 0x3F, 0x98, 0x1C, 0x4D, 0x0D, 0x6A, 0x27, 0x97, 0xB6, 0x9F, 0x12,
474 0xF6, 0xE9, 0x4C, 0x21, 0x2F, 0x14, 0x68, 0x5A, 0xC4, 0xB7, 0x4B, 0x12, 0xBB, 0x6F,
475 0xDB, 0xFF, 0xA2, 0xD1, 0x7D, 0x87, 0xC5, 0x39, 0x2A, 0xAB, 0x79, 0x2D, 0xC2, 0x52,
476 0xD5, 0xDE, 0x45, 0x33, 0xCC, 0x95, 0x18, 0xD3, 0x8A, 0xA8, 0xDB, 0xF1, 0x92, 0x5A,
477 0xB9, 0x23, 0x86, 0xED, 0xD4, 0x00, 0x99, 0x23,
478 ];
479 assert_eq!(hash.hash, known_hash);
480 }
481}