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