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