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