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