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