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