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