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