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