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