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