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