ecaps2.rs

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