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