ecaps2.rs

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