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