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