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