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