ecaps2.rs

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