Przeglądaj źródła

Include signedPreKeySignature in published bundle

updates #497
JC Brand 7 lat temu
rodzic
commit
b80a77a21c
4 zmienionych plików z 103 dodań i 20 usunięć
  1. 6 6
      dist/converse.js
  2. 81 2
      spec/omemo.js
  3. 9 6
      src/converse-omemo.js
  4. 7 6
      tests/mock.js

+ 6 - 6
dist/converse.js

@@ -73396,6 +73396,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
       _converse.api.promises.add(['OMEMOInitialized']);
 
+      _converse.NUM_PREKEYS = 100; // Set here so that tests can override
+
       function generateDeviceID() {
         /* Generates a device ID, making sure that it's unique */
         const existing_ids = _converse.devicelists.get(_converse.bare_jid).devices.pluck('id');
@@ -73420,7 +73422,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
          * start using OMEMO is they need to generate an IdentityKey
          * and a Device ID. The IdentityKey is a Curve25519 [6]
          * public/private Key pair. The Device ID is a randomly
-         * generated integer between 1 and 2^31 - 1. 
+         * generated integer between 1 and 2^31 - 1.
          */
         return new Promise((resolve, reject) => {
           libsignal.KeyHelper.generateIdentityKeyPair().then(identity_keypair => {
@@ -73433,7 +73435,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
             libsignal.KeyHelper.generateSignedPreKey(identity_keypair, signed_prekey_id).then(signed_prekey => {
               data['signed_prekey'] = signed_prekey;
 
-              const key_promises = _.map(_.range(0, 100), id => libsignal.KeyHelper.generatePreKey(id));
+              const key_promises = _.map(_.range(0, _converse.NUM_PREKEYS), id => libsignal.KeyHelper.generatePreKey(id));
 
               Promise.all(key_promises).then(keys => {
                 data['prekeys'] = keys;
@@ -73724,8 +73726,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
       function publishBundle() {
         const store = _converse.omemo_store,
-              signed_prekey = store.get('signed_prekey'),
-              identity_key = u.arrayBufferToBase64(store.get('identity_keypair').pubKey);
+              signed_prekey = store.get('signed_prekey');
         return new Promise((resolve, reject) => {
           const stanza = $iq({
             'from': _converse.bare_jid,
@@ -73738,8 +73739,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
             'xmlns': Strophe.NS.OMEMO
           }).c('signedPreKeyPublic', {
             'signedPreKeyId': signed_prekey.keyId
-          }).t(u.arrayBufferToBase64(signed_prekey.keyPair.pubKey)).up().c('signedPreKeySignature').up() // TODO
-          .c('identityKey').t(identity_key).up().c('prekeys');
+          }).t(u.arrayBufferToBase64(signed_prekey.keyPair.pubKey)).up().c('signedPreKeySignature').t(u.arrayBufferToBase64(signed_prekey.signature)).up().c('identityKey').t(u.arrayBufferToBase64(store.get('identity_keypair').pubKey)).up().c('prekeys');
 
           _.forEach(store.get('prekeys'), prekey => {
             stanza.c('preKeyPublic', {

+ 81 - 2
spec/omemo.js

@@ -321,14 +321,93 @@
             });
         }));
 
+        it("publishes a bundle with which an encrypted session can be created",
+            mock.initConverseWithPromises(
+                null, ['rosterGroupsFetched'], {},
+                function (done, _converse) {
+
+            let iq_stanza;
+            test_utils.createContacts(_converse, 'current', 1);
+            const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
+
+            test_utils.waitUntil(function () {
+                return _.filter(
+                    _converse.connection.IQ_stanzas,
+                    (iq) => {
+                        const node = iq.nodeTree.querySelector('iq[to="'+_converse.bare_jid+'"] query[node="eu.siacs.conversations.axolotl.devicelist"]');
+                        if (node) { iq_stanza = iq.nodeTree;}
+                        return node;
+                    }).length;
+            }).then(function () {
+                _converse.NUM_PREKEYS = 2; // Restrict to 2, otherwise the resulting stanza is too large to easily test
+
+                const stanza = $iq({
+                    'from': contact_jid,
+                    'id': iq_stanza.getAttribute('id'),
+                    'to': _converse.bare_jid,
+                    'type': 'result',
+                }).c('query', {
+                    'xmlns': 'http://jabber.org/protocol/disco#items',
+                    'node': 'eu.siacs.conversations.axolotl.devicelist'
+                }).c('device', {'id': '482886413b977930064a5888b92134fe'}).up()
+                _converse.connection._dataRecv(test_utils.createRequest(stanza));
+
+                expect(_converse.devicelists.length).toBe(1);
+
+                test_utils.openChatBoxFor(_converse, contact_jid);
+                return test_utils.waitUntil(() => {
+                    return _.filter(_converse.connection.IQ_stanzas, function (iq) {
+                        const node = iq.nodeTree.querySelector('publish[node="eu.siacs.conversations.axolotl.devicelist"]');
+                        if (node) { iq_stanza = iq.nodeTree; }
+                        return node;
+                    }).length;
+                });
+            }).then(function () {
+                const stanza = $iq({
+                    'from': _converse.bare_jid,
+                    'id': iq_stanza.getAttribute('id'),
+                    'to': _converse.bare_jid,
+                    'type': 'result'});
+                _converse.connection._dataRecv(test_utils.createRequest(stanza));
+
+                return test_utils.waitUntil(() => {
+                    return _.filter(_converse.connection.IQ_stanzas, function (iq) {
+                        const node = iq.nodeTree.querySelector('publish[node="eu.siacs.conversations.axolotl.bundles:123456789"]');
+                        if (node) { iq_stanza = iq.nodeTree; }
+                        return node;
+                    }).length;
+                });
+            }).then(function () {
+                expect(iq_stanza.outerHTML).toBe(
+                    `<iq from="dummy@localhost" type="set" xmlns="jabber:client" id="${iq_stanza.getAttribute('id')}">`+
+                        `<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
+                            `<publish node="eu.siacs.conversations.axolotl.bundles:123456789">`+
+                                `<item>`+
+                                    `<bundle xmlns="eu.siacs.conversations.axolotl">`+
+                                        `<signedPreKeyPublic signedPreKeyId="0">${btoa('1234')}</signedPreKeyPublic>`+
+                                            `<signedPreKeySignature>${btoa('11112222333344445555')}</signedPreKeySignature>`+
+                                            `<identityKey>${btoa('1234')}</identityKey>`+
+                                        `<prekeys>`+
+                                            `<preKeyPublic preKeyId="0">${btoa('1234')}</preKeyPublic>`+
+                                            `<preKeyPublic preKeyId="1">${btoa('1234')}</preKeyPublic>`+
+                                        `</prekeys>`+
+                                    `</bundle>`+
+                                `</item>`+
+                            `</publish>`+
+                        `</pubsub>`+
+                    `</iq>`)
+                done();
+            });
+        }));
+
         it("adds a toolbar button for starting an encrypted chat session",
             mock.initConverseWithPromises(
                 null, ['rosterGroupsFetched'], {},
                 function (done, _converse) {
 
             let iq_stanza;
-            test_utils.createContacts(_converse, 'current');
-            const contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
+            test_utils.createContacts(_converse, 'current', 1);
+            const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
 
             test_utils.waitUntil(function () {
                 return _.filter(

+ 9 - 6
src/converse-omemo.js

@@ -214,6 +214,8 @@
 
             _converse.api.promises.add(['OMEMOInitialized']);
 
+            _converse.NUM_PREKEYS = 100; // Set here so that tests can override
+
 
             function generateDeviceID () {
                 /* Generates a device ID, making sure that it's unique */
@@ -236,7 +238,7 @@
                  * start using OMEMO is they need to generate an IdentityKey
                  * and a Device ID. The IdentityKey is a Curve25519 [6]
                  * public/private Key pair. The Device ID is a randomly
-                 * generated integer between 1 and 2^31 - 1. 
+                 * generated integer between 1 and 2^31 - 1.
                  */
                 return new Promise((resolve, reject) => {
                     libsignal.KeyHelper.generateIdentityKeyPair().then((identity_keypair) => {
@@ -249,7 +251,7 @@
                         libsignal.KeyHelper.generateSignedPreKey(identity_keypair, signed_prekey_id)
                             .then((signed_prekey) => {
                                 data['signed_prekey'] = signed_prekey;
-                                const key_promises = _.map(_.range(0, 100), (id) => libsignal.KeyHelper.generatePreKey(id));
+                                const key_promises = _.map(_.range(0, _converse.NUM_PREKEYS), (id) => libsignal.KeyHelper.generatePreKey(id));
                                 Promise.all(key_promises).then((keys) => {
                                     data['prekeys'] = keys;
                                     resolve(data)
@@ -515,8 +517,7 @@
 
             function publishBundle () {
                 const store = _converse.omemo_store,
-                      signed_prekey = store.get('signed_prekey'),
-                      identity_key = u.arrayBufferToBase64(store.get('identity_keypair').pubKey);
+                      signed_prekey = store.get('signed_prekey');
 
                 return new Promise((resolve, reject) => {
                     const stanza = $iq({
@@ -528,8 +529,10 @@
                                 .c('bundle', {'xmlns': Strophe.NS.OMEMO})
                                     .c('signedPreKeyPublic', {'signedPreKeyId': signed_prekey.keyId})
                                         .t(u.arrayBufferToBase64(signed_prekey.keyPair.pubKey)).up()
-                                    .c('signedPreKeySignature').up()  // TODO
-                                    .c('identityKey').t(identity_key).up()
+                                    .c('signedPreKeySignature')
+                                        .t(u.arrayBufferToBase64(signed_prekey.signature)).up()
+                                    .c('identityKey')
+                                        .t(u.arrayBufferToBase64(store.get('identity_keypair').pubKey)).up()
                                     .c('prekeys');
                     _.forEach(
                         store.get('prekeys'),

+ 7 - 6
tests/mock.js

@@ -11,8 +11,8 @@
         'KeyHelper': {
             'generateIdentityKeyPair': function () {
                 return Promise.resolve({
-                    'pubKey': 1234,
-                    'privKey': 4321
+                    'pubKey': new TextEncoder('utf-8').encode('1234'),
+                    'privKey': new TextEncoder('utf-8').encode('4321')
                 });
             },
             'generateRegistrationId': function () {
@@ -22,17 +22,18 @@
                 return Promise.resolve({
                     'keyId': keyid,
                     'keyPair': {
-                        'pubKey': 1234,
-                        'privKey': 4321
+                        'pubKey': new TextEncoder('utf-8').encode('1234'),
+                        'privKey': new TextEncoder('utf-8').encode('4321')
                     }
                 });
             },
             'generateSignedPreKey': function (identity_keypair, keyid) {
                 return Promise.resolve({
+                    'signature': new TextEncoder('utf-8').encode('11112222333344445555'),
                     'keyId': keyid,
                     'keyPair': {
-                        'pubKey': 1234,
-                        'privKey': 4321
+                        'pubKey': new TextEncoder('utf-8').encode('1234'),
+                        'privKey': new TextEncoder('utf-8').encode('4321')
                     }
                 });
             }