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