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