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