ecaps2.rs

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