Commit b80a77a2 authored by JC Brand's avatar JC Brand

Include signedPreKeySignature in published bundle

updates #497
parent bf139279
...@@ -73396,6 +73396,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -73396,6 +73396,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
_converse.api.promises.add(['OMEMOInitialized']); _converse.api.promises.add(['OMEMOInitialized']);
_converse.NUM_PREKEYS = 100; // Set here so that tests can override
function generateDeviceID() { function generateDeviceID() {
/* Generates a device ID, making sure that it's unique */ /* Generates a device ID, making sure that it's unique */
const existing_ids = _converse.devicelists.get(_converse.bare_jid).devices.pluck('id'); 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_ ...@@ -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 * start using OMEMO is they need to generate an IdentityKey
* and a Device ID. The IdentityKey is a Curve25519 [6] * and a Device ID. The IdentityKey is a Curve25519 [6]
* public/private Key pair. The Device ID is a randomly * 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) => { return new Promise((resolve, reject) => {
libsignal.KeyHelper.generateIdentityKeyPair().then(identity_keypair => { libsignal.KeyHelper.generateIdentityKeyPair().then(identity_keypair => {
...@@ -73433,7 +73435,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -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 => { libsignal.KeyHelper.generateSignedPreKey(identity_keypair, signed_prekey_id).then(signed_prekey => {
data['signed_prekey'] = 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 => { Promise.all(key_promises).then(keys => {
data['prekeys'] = keys; data['prekeys'] = keys;
...@@ -73724,8 +73726,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -73724,8 +73726,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
function publishBundle() { function publishBundle() {
const store = _converse.omemo_store, const store = _converse.omemo_store,
signed_prekey = store.get('signed_prekey'), signed_prekey = store.get('signed_prekey');
identity_key = u.arrayBufferToBase64(store.get('identity_keypair').pubKey);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const stanza = $iq({ const stanza = $iq({
'from': _converse.bare_jid, 'from': _converse.bare_jid,
...@@ -73738,8 +73739,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -73738,8 +73739,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'xmlns': Strophe.NS.OMEMO 'xmlns': Strophe.NS.OMEMO
}).c('signedPreKeyPublic', { }).c('signedPreKeyPublic', {
'signedPreKeyId': signed_prekey.keyId 'signedPreKeyId': signed_prekey.keyId
}).t(u.arrayBufferToBase64(signed_prekey.keyPair.pubKey)).up().c('signedPreKeySignature').up() // TODO }).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');
.c('identityKey').t(identity_key).up().c('prekeys');
_.forEach(store.get('prekeys'), prekey => { _.forEach(store.get('prekeys'), prekey => {
stanza.c('preKeyPublic', { stanza.c('preKeyPublic', {
...@@ -321,14 +321,93 @@ ...@@ -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", it("adds a toolbar button for starting an encrypted chat session",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
let iq_stanza; let iq_stanza;
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current', 1);
const contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.waitUntil(function () { test_utils.waitUntil(function () {
return _.filter( return _.filter(
......
...@@ -214,6 +214,8 @@ ...@@ -214,6 +214,8 @@
_converse.api.promises.add(['OMEMOInitialized']); _converse.api.promises.add(['OMEMOInitialized']);
_converse.NUM_PREKEYS = 100; // Set here so that tests can override
function generateDeviceID () { function generateDeviceID () {
/* Generates a device ID, making sure that it's unique */ /* Generates a device ID, making sure that it's unique */
...@@ -236,7 +238,7 @@ ...@@ -236,7 +238,7 @@
* start using OMEMO is they need to generate an IdentityKey * start using OMEMO is they need to generate an IdentityKey
* and a Device ID. The IdentityKey is a Curve25519 [6] * and a Device ID. The IdentityKey is a Curve25519 [6]
* public/private Key pair. The Device ID is a randomly * 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) => { return new Promise((resolve, reject) => {
libsignal.KeyHelper.generateIdentityKeyPair().then((identity_keypair) => { libsignal.KeyHelper.generateIdentityKeyPair().then((identity_keypair) => {
...@@ -249,7 +251,7 @@ ...@@ -249,7 +251,7 @@
libsignal.KeyHelper.generateSignedPreKey(identity_keypair, signed_prekey_id) libsignal.KeyHelper.generateSignedPreKey(identity_keypair, signed_prekey_id)
.then((signed_prekey) => { .then((signed_prekey) => {
data['signed_prekey'] = 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) => { Promise.all(key_promises).then((keys) => {
data['prekeys'] = keys; data['prekeys'] = keys;
resolve(data) resolve(data)
...@@ -515,8 +517,7 @@ ...@@ -515,8 +517,7 @@
function publishBundle () { function publishBundle () {
const store = _converse.omemo_store, const store = _converse.omemo_store,
signed_prekey = store.get('signed_prekey'), signed_prekey = store.get('signed_prekey');
identity_key = u.arrayBufferToBase64(store.get('identity_keypair').pubKey);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const stanza = $iq({ const stanza = $iq({
...@@ -528,8 +529,10 @@ ...@@ -528,8 +529,10 @@
.c('bundle', {'xmlns': Strophe.NS.OMEMO}) .c('bundle', {'xmlns': Strophe.NS.OMEMO})
.c('signedPreKeyPublic', {'signedPreKeyId': signed_prekey.keyId}) .c('signedPreKeyPublic', {'signedPreKeyId': signed_prekey.keyId})
.t(u.arrayBufferToBase64(signed_prekey.keyPair.pubKey)).up() .t(u.arrayBufferToBase64(signed_prekey.keyPair.pubKey)).up()
.c('signedPreKeySignature').up() // TODO .c('signedPreKeySignature')
.c('identityKey').t(identity_key).up() .t(u.arrayBufferToBase64(signed_prekey.signature)).up()
.c('identityKey')
.t(u.arrayBufferToBase64(store.get('identity_keypair').pubKey)).up()
.c('prekeys'); .c('prekeys');
_.forEach( _.forEach(
store.get('prekeys'), store.get('prekeys'),
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
'KeyHelper': { 'KeyHelper': {
'generateIdentityKeyPair': function () { 'generateIdentityKeyPair': function () {
return Promise.resolve({ return Promise.resolve({
'pubKey': 1234, 'pubKey': new TextEncoder('utf-8').encode('1234'),
'privKey': 4321 'privKey': new TextEncoder('utf-8').encode('4321')
}); });
}, },
'generateRegistrationId': function () { 'generateRegistrationId': function () {
...@@ -22,17 +22,18 @@ ...@@ -22,17 +22,18 @@
return Promise.resolve({ return Promise.resolve({
'keyId': keyid, 'keyId': keyid,
'keyPair': { 'keyPair': {
'pubKey': 1234, 'pubKey': new TextEncoder('utf-8').encode('1234'),
'privKey': 4321 'privKey': new TextEncoder('utf-8').encode('4321')
} }
}); });
}, },
'generateSignedPreKey': function (identity_keypair, keyid) { 'generateSignedPreKey': function (identity_keypair, keyid) {
return Promise.resolve({ return Promise.resolve({
'signature': new TextEncoder('utf-8').encode('11112222333344445555'),
'keyId': keyid, 'keyId': keyid,
'keyPair': { 'keyPair': {
'pubKey': 1234, 'pubKey': new TextEncoder('utf-8').encode('1234'),
'privKey': 4321 'privKey': new TextEncoder('utf-8').encode('4321')
} }
}); });
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment