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 presence::PresencePayload;
8use disco::{Feature, Identity, DiscoInfoResult, DiscoInfoQuery};
9use data_forms::DataForm;
10use hashes::{Hash, Algo};
11
12use 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 error::Error;
154
155 #[test]
156 fn test_size() {
157 assert_size!(ECaps2, 24);
158 }
159
160 #[test]
161 fn test_parse() {
162 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();
163 let ecaps2 = ECaps2::try_from(elem).unwrap();
164 assert_eq!(ecaps2.hashes.len(), 2);
165 assert_eq!(ecaps2.hashes[0].algo, Algo::Sha_256);
166 assert_eq!(ecaps2.hashes[0].hash, base64::decode("K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=").unwrap());
167 assert_eq!(ecaps2.hashes[1].algo, Algo::Sha3_256);
168 assert_eq!(ecaps2.hashes[1].hash, base64::decode("+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=").unwrap());
169 }
170
171 #[test]
172 fn test_invalid_child() {
173 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();
174 let error = ECaps2::try_from(elem).unwrap_err();
175 let message = match error {
176 Error::ParseError(string) => string,
177 _ => panic!(),
178 };
179 assert_eq!(message, "Unknown child in c element.");
180 }
181
182 #[test]
183 fn test_simple() {
184 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();
185 let disco = DiscoInfoResult::try_from(elem).unwrap();
186 let ecaps2 = compute_disco(&disco);
187 assert_eq!(ecaps2.len(), 54);
188 }
189
190 #[test]
191 fn test_xep_ex1() {
192 let elem: Element = r#"
193<query xmlns="http://jabber.org/protocol/disco#info">
194 <identity category="client" name="BombusMod" type="mobile"/>
195 <feature var="http://jabber.org/protocol/si"/>
196 <feature var="http://jabber.org/protocol/bytestreams"/>
197 <feature var="http://jabber.org/protocol/chatstates"/>
198 <feature var="http://jabber.org/protocol/disco#info"/>
199 <feature var="http://jabber.org/protocol/disco#items"/>
200 <feature var="urn:xmpp:ping"/>
201 <feature var="jabber:iq:time"/>
202 <feature var="jabber:iq:privacy"/>
203 <feature var="jabber:iq:version"/>
204 <feature var="http://jabber.org/protocol/rosterx"/>
205 <feature var="urn:xmpp:time"/>
206 <feature var="jabber:x:oob"/>
207 <feature var="http://jabber.org/protocol/ibb"/>
208 <feature var="http://jabber.org/protocol/si/profile/file-transfer"/>
209 <feature var="urn:xmpp:receipts"/>
210 <feature var="jabber:iq:roster"/>
211 <feature var="jabber:iq:last"/>
212</query>
213"#.parse().unwrap();
214 let expected = vec![104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98,
215 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111,
216 108, 47, 98, 121, 116, 101, 115, 116, 114, 101, 97, 109, 115, 31,
217 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111,
218 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 99, 104,
219 97, 116, 115, 116, 97, 116, 101, 115, 31, 104, 116, 116, 112, 58,
220 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
221 111, 116, 111, 99, 111, 108, 47, 100, 105, 115, 99, 111, 35, 105,
222 110, 102, 111, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98,
223 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111,
224 108, 47, 100, 105, 115, 99, 111, 35, 105, 116, 101, 109, 115, 31,
225 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111,
226 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 105, 98,
227 98, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114,
228 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47,
229 114, 111, 115, 116, 101, 114, 120, 31, 104, 116, 116, 112, 58, 47,
230 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
231 111, 116, 111, 99, 111, 108, 47, 115, 105, 31, 104, 116, 116, 112,
232 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112,
233 114, 111, 116, 111, 99, 111, 108, 47, 115, 105, 47, 112, 114, 111,
234 102, 105, 108, 101, 47, 102, 105, 108, 101, 45, 116, 114, 97, 110,
235 115, 102, 101, 114, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113,
236 58, 108, 97, 115, 116, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113,
237 58, 112, 114, 105, 118, 97, 99, 121, 31, 106, 97, 98, 98, 101, 114,
238 58, 105, 113, 58, 114, 111, 115, 116, 101, 114, 31, 106, 97, 98,
239 98, 101, 114, 58, 105, 113, 58, 116, 105, 109, 101, 31, 106, 97,
240 98, 98, 101, 114, 58, 105, 113, 58, 118, 101, 114, 115, 105, 111,
241 110, 31, 106, 97, 98, 98, 101, 114, 58, 120, 58, 111, 111, 98, 31,
242 117, 114, 110, 58, 120, 109, 112, 112, 58, 112, 105, 110, 103, 31,
243 117, 114, 110, 58, 120, 109, 112, 112, 58, 114, 101, 99, 101, 105,
244 112, 116, 115, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58, 116,
245 105, 109, 101, 31, 28, 99, 108, 105, 101, 110, 116, 31, 109, 111,
246 98, 105, 108, 101, 31, 31, 66, 111, 109, 98, 117, 115, 77, 111,
247 100, 31, 30, 28, 28];
248 let disco = DiscoInfoResult::try_from(elem).unwrap();
249 let ecaps2 = compute_disco(&disco);
250 assert_eq!(ecaps2.len(), 0x1d9);
251 assert_eq!(ecaps2, expected);
252
253 let sha_256 = hash_ecaps2(&ecaps2, Algo::Sha_256).unwrap();
254 assert_eq!(sha_256.hash, base64::decode("kzBZbkqJ3ADrj7v08reD1qcWUwNGHaidNUgD7nHpiw8=").unwrap());
255 let sha3_256 = hash_ecaps2(&ecaps2, Algo::Sha3_256).unwrap();
256 assert_eq!(sha3_256.hash, base64::decode("79mdYAfU9rEdTOcWDO7UEAt6E56SUzk/g6TnqUeuD9Q=").unwrap());
257 }
258
259 #[test]
260 fn test_xep_ex2() {
261 let elem: Element = r#"
262<query xmlns="http://jabber.org/protocol/disco#info">
263 <identity category="client" name="Tkabber" type="pc" xml:lang="en"/>
264 <identity category="client" name="Ткаббер" type="pc" xml:lang="ru"/>
265 <feature var="games:board"/>
266 <feature var="http://jabber.org/protocol/activity"/>
267 <feature var="http://jabber.org/protocol/activity+notify"/>
268 <feature var="http://jabber.org/protocol/bytestreams"/>
269 <feature var="http://jabber.org/protocol/chatstates"/>
270 <feature var="http://jabber.org/protocol/commands"/>
271 <feature var="http://jabber.org/protocol/disco#info"/>
272 <feature var="http://jabber.org/protocol/disco#items"/>
273 <feature var="http://jabber.org/protocol/evil"/>
274 <feature var="http://jabber.org/protocol/feature-neg"/>
275 <feature var="http://jabber.org/protocol/geoloc"/>
276 <feature var="http://jabber.org/protocol/geoloc+notify"/>
277 <feature var="http://jabber.org/protocol/ibb"/>
278 <feature var="http://jabber.org/protocol/iqibb"/>
279 <feature var="http://jabber.org/protocol/mood"/>
280 <feature var="http://jabber.org/protocol/mood+notify"/>
281 <feature var="http://jabber.org/protocol/rosterx"/>
282 <feature var="http://jabber.org/protocol/si"/>
283 <feature var="http://jabber.org/protocol/si/profile/file-transfer"/>
284 <feature var="http://jabber.org/protocol/tune"/>
285 <feature var="http://www.facebook.com/xmpp/messages"/>
286 <feature var="http://www.xmpp.org/extensions/xep-0084.html#ns-metadata+notify"/>
287 <feature var="jabber:iq:avatar"/>
288 <feature var="jabber:iq:browse"/>
289 <feature var="jabber:iq:dtcp"/>
290 <feature var="jabber:iq:filexfer"/>
291 <feature var="jabber:iq:ibb"/>
292 <feature var="jabber:iq:inband"/>
293 <feature var="jabber:iq:jidlink"/>
294 <feature var="jabber:iq:last"/>
295 <feature var="jabber:iq:oob"/>
296 <feature var="jabber:iq:privacy"/>
297 <feature var="jabber:iq:roster"/>
298 <feature var="jabber:iq:time"/>
299 <feature var="jabber:iq:version"/>
300 <feature var="jabber:x:data"/>
301 <feature var="jabber:x:event"/>
302 <feature var="jabber:x:oob"/>
303 <feature var="urn:xmpp:avatar:metadata+notify"/>
304 <feature var="urn:xmpp:ping"/>
305 <feature var="urn:xmpp:receipts"/>
306 <feature var="urn:xmpp:time"/>
307 <x xmlns="jabber:x:data" type="result">
308 <field type="hidden" var="FORM_TYPE">
309 <value>urn:xmpp:dataforms:softwareinfo</value>
310 </field>
311 <field var="software">
312 <value>Tkabber</value>
313 </field>
314 <field var="software_version">
315 <value>0.11.1-svn-20111216-mod (Tcl/Tk 8.6b2)</value>
316 </field>
317 <field var="os">
318 <value>Windows</value>
319 </field>
320 <field var="os_version">
321 <value>XP</value>
322 </field>
323 </x>
324</query>
325"#.parse().unwrap();
326 let expected = vec![103, 97, 109, 101, 115, 58, 98, 111, 97, 114, 100,
327 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46,
328 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 97,
329 99, 116, 105, 118, 105, 116, 121, 31, 104, 116, 116, 112, 58, 47,
330 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
331 111, 116, 111, 99, 111, 108, 47, 97, 99, 116, 105, 118, 105, 116,
332 121, 43, 110, 111, 116, 105, 102, 121, 31, 104, 116, 116, 112, 58,
333 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
334 111, 116, 111, 99, 111, 108, 47, 98, 121, 116, 101, 115, 116, 114,
335 101, 97, 109, 115, 31, 104, 116, 116, 112, 58,47, 47, 106, 97, 98,
336 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99,
337 111, 108, 47, 99, 104, 97, 116, 115, 116, 97, 116, 101, 115, 31,
338 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111,
339 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 99, 111,
340 109, 109, 97, 110, 100, 115, 31,104,116, 116, 112, 58, 47, 47, 106,
341 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116,
342 111, 99, 111, 108, 47, 100, 105, 115, 99, 111, 35, 105, 110, 102,
343 111, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114,
344 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47,
345 100, 105, 115, 99, 111, 35, 105, 116, 101, 109, 115, 31, 104, 116,
346 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103,
347 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 101, 118, 105, 108,
348 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46,
349 111, 114, 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 102,
350 101, 97, 116, 117, 114, 101, 45, 110, 101, 103, 31, 104, 116, 116,
351 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47,
352 112, 114, 111, 116, 111, 99, 111, 108, 47, 103, 101, 111, 108, 111,
353 99, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114,
354 46, 111, 114, 103, 47, 112, 114, 111, 116, 111, 99,111, 108, 47,
355 103, 101, 111, 108, 111, 99, 43, 110, 111, 116, 105, 102, 121, 31,
356 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111,
357 114, 103,47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 105, 98,
358 98, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114,
359 46, 111, 114, 103, 47, 112, 114, 111,116, 111, 99, 111, 108, 47,
360 105, 113, 105, 98, 98, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97,
361 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116,111,
362 99, 111, 108, 47, 109, 111, 111, 100, 31, 104, 116, 116, 112, 58,
363 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
364 111, 116, 111, 99, 111,108, 47, 109, 111, 111, 100, 43, 110, 111,
365 116, 105, 102, 121, 31, 104, 116, 116, 112, 58, 47, 47, 106, 97,
366 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114, 111, 116, 111,
367 99, 111, 108, 47, 114, 111, 115, 116, 101, 114, 120, 31, 104, 116,
368 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103,
369 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 115, 105, 31, 104,
370 116, 116, 112, 58, 47, 47, 106, 97, 98, 98, 101, 114, 46, 111, 114,
371 103, 47, 112, 114, 111, 116, 111, 99, 111, 108, 47, 115, 105, 47,
372 112, 114, 111, 102, 105, 108, 101, 47, 102, 105, 108, 101, 45, 116,
373 114, 97, 110, 115, 102, 101, 114, 31, 104, 116, 116, 112, 58, 47,
374 47, 106, 97, 98, 98, 101, 114, 46, 111, 114, 103, 47, 112, 114,
375 111, 116, 111, 99, 111, 108, 47, 116, 117, 110, 101, 31, 104, 116,
376 116, 112, 58, 47, 47, 119, 119, 119, 46, 102, 97, 99, 101, 98, 111,
377 111, 107, 46, 99, 111, 109, 47, 120, 109, 112, 112, 47, 109, 101,
378 115, 115, 97, 103, 101, 115, 31, 104, 116, 116, 112, 58, 47, 47,
379 119, 119, 119, 46, 120, 109, 112, 112, 46, 111, 114, 103, 47, 101,
380 120, 116, 101, 110, 115, 105, 111, 110, 115, 47, 120, 101, 112, 45,
381 48, 48, 56, 52, 46, 104, 116, 109, 108, 35, 110, 115, 45, 109, 101,
382 116, 97, 100, 97, 116, 97, 43, 110, 111, 116, 105, 102, 121, 31,
383 106, 97, 98, 98, 101, 114,58, 105,113, 58, 97, 118, 97, 116, 97,
384 114, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 98, 114, 111,
385 119, 115, 101, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58,
386 100, 116, 99, 112, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58,
387 102, 105, 108, 101, 120, 102, 101, 114, 31, 106, 97, 98, 98, 101,
388 114, 58, 105, 113, 58, 105, 98, 98, 31, 106, 97, 98, 98, 101, 114,
389 58, 105, 113, 58, 105, 110, 98, 97, 110, 100, 31, 106, 97, 98, 98,
390 101, 114, 58, 105, 113, 58, 106, 105, 100, 108, 105, 110, 107, 31,
391 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 108, 97, 115, 116, 31,
392 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 111, 111, 98, 31, 106,
393 97,98, 98, 101, 114, 58, 105, 113, 58, 112, 114, 105, 118, 97, 99,
394 121, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58, 114, 111,
395 115, 116, 101, 114,31, 106, 97, 98, 98, 101, 114, 58, 105, 113, 58,
396 116, 105, 109, 101, 31, 106, 97, 98, 98, 101, 114, 58, 105, 113,
397 58, 118, 101, 114, 115, 105, 111, 110, 31, 106, 97, 98, 98, 101,
398 114, 58, 120, 58, 100, 97, 116, 97, 31, 106, 97, 98, 98, 101, 114,
399 58, 120, 58, 101, 118, 101, 110, 116, 31, 106, 97, 98, 98, 101,
400 114, 58, 120, 58, 111, 111, 98, 31, 117, 114, 110, 58, 120, 109,
401 112, 112, 58, 97, 118, 97, 116, 97, 114, 58, 109, 101, 116, 97,
402 100, 97, 116, 97, 43, 110, 111, 116, 105, 102, 121,31, 117, 114,
403 110, 58, 120, 109, 112, 112, 58, 112, 105, 110, 103, 31, 117, 114,
404 110, 58, 120, 109, 112, 112, 58, 114, 101, 99, 101, 105, 112, 116,
405 115, 31, 117, 114, 110, 58, 120, 109, 112, 112, 58, 116, 105, 109,
406 101, 31, 28, 99, 108, 105, 101, 110, 116, 31, 112, 99, 31, 101,
407 110, 31, 84, 107, 97, 98, 98, 101, 114,31, 30, 99, 108, 105, 101,
408 110, 116, 31, 112, 99, 31, 114, 117, 31, 208, 162, 208, 186, 208,
409 176, 208, 177, 208, 177, 208, 181, 209, 128, 31, 30, 28, 70, 79,
410 82, 77, 95, 84, 89, 80, 69, 31, 117, 114, 110, 58, 120, 109, 112,
411 112, 58, 100, 97, 116, 97, 102, 111, 114, 109, 115, 58, 115, 111,
412 102, 116, 119, 97, 114, 101,105, 110, 102, 111, 31, 30, 111, 115,
413 31, 87, 105, 110, 100, 111, 119, 115, 31, 30, 111, 115, 95, 118,
414 101, 114, 115, 105, 111, 110, 31, 88, 80, 31, 30, 115, 111, 102,
415 116, 119, 97, 114, 101, 31, 84, 107, 97, 98, 98, 101, 114, 31, 30,
416 115, 111, 102, 116, 119, 97, 114, 101, 95, 118, 101, 114, 115, 105,
417 111, 110, 31, 48, 46, 49, 49, 46, 49, 45, 115, 118, 110, 45, 50,
418 48, 49, 49, 49, 50, 49, 54, 45, 109, 111, 100, 32, 40, 84, 99, 108,
419 47, 84, 107, 32, 56, 46,54, 98, 50, 41, 31, 30, 29, 28];
420 let disco = DiscoInfoResult::try_from(elem).unwrap();
421 let ecaps2 = compute_disco(&disco);
422 assert_eq!(ecaps2.len(), 0x543);
423 assert_eq!(ecaps2, expected);
424
425 let sha_256 = hash_ecaps2(&ecaps2, Algo::Sha_256).unwrap();
426 assert_eq!(sha_256.hash, base64::decode("u79ZroNJbdSWhdSp311mddz44oHHPsEBntQ5b1jqBSY=").unwrap());
427 let sha3_256 = hash_ecaps2(&ecaps2, Algo::Sha3_256).unwrap();
428 assert_eq!(sha3_256.hash, base64::decode("XpUJzLAc93258sMECZ3FJpebkzuyNXDzRNwQog8eycg=").unwrap());
429 }
430
431 #[test]
432 fn test_blake2b_512() {
433 let hash = hash_ecaps2("abc".as_bytes(), Algo::Blake2b_512).unwrap();
434 let known_hash: Vec<u8> = vec!(
435 0xBA, 0x80, 0xA5, 0x3F, 0x98, 0x1C, 0x4D, 0x0D, 0x6A, 0x27, 0x97, 0xB6, 0x9F, 0x12, 0xF6, 0xE9,
436 0x4C, 0x21, 0x2F, 0x14, 0x68, 0x5A, 0xC4, 0xB7, 0x4B, 0x12, 0xBB, 0x6F, 0xDB, 0xFF, 0xA2, 0xD1,
437 0x7D, 0x87, 0xC5, 0x39, 0x2A, 0xAB, 0x79, 0x2D, 0xC2, 0x52, 0xD5, 0xDE, 0x45, 0x33, 0xCC, 0x95,
438 0x18, 0xD3, 0x8A, 0xA8, 0xDB, 0xF1, 0x92, 0x5A, 0xB9, 0x23, 0x86, 0xED, 0xD4, 0x00, 0x99, 0x23,
439 );
440 assert_eq!(hash.hash, known_hash);
441 }
442}