Test that own devices (from other clients) get included
when sending out encrypted messages. updates #497
This commit is contained in:
parent
a3593dbc7d
commit
e774e9d1af
@ -10,7 +10,7 @@
|
||||
|
||||
describe("The OMEMO module", function() {
|
||||
|
||||
it("enables encrypted messages to be sent",
|
||||
it("enables encrypted messages to be sent and received",
|
||||
mock.initConverseWithPromises(
|
||||
null, ['rosterGroupsFetched'], {},
|
||||
function (done, _converse) {
|
||||
@ -83,7 +83,9 @@
|
||||
return _.filter(
|
||||
_converse.connection.IQ_stanzas,
|
||||
(iq) => {
|
||||
const node = iq.nodeTree.querySelector('iq[to="'+contact_jid+'"] items[node="eu.siacs.conversations.axolotl.bundles:555"]');
|
||||
const node = iq.nodeTree.querySelector(
|
||||
'iq[to="'+contact_jid+'"] items[node="eu.siacs.conversations.axolotl.bundles:555"]'
|
||||
);
|
||||
if (node) { iq_stanza = iq.nodeTree; }
|
||||
return node;
|
||||
}).length;
|
||||
@ -106,6 +108,36 @@
|
||||
.c('preKeyPublic', {'preKeyId': '1'}).t(btoa('1001')).up()
|
||||
.c('preKeyPublic', {'preKeyId': '2'}).t(btoa('1002')).up()
|
||||
.c('preKeyPublic', {'preKeyId': '3'}).t(btoa('1003'));
|
||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||
return test_utils.waitUntil(() => {
|
||||
return _.filter(
|
||||
_converse.connection.IQ_stanzas,
|
||||
(iq) => {
|
||||
const node = iq.nodeTree.querySelector(
|
||||
'iq[to="'+_converse.bare_jid+'"] items[node="eu.siacs.conversations.axolotl.bundles:482886413b977930064a5888b92134fe"]'
|
||||
);
|
||||
if (node) { iq_stanza = iq.nodeTree; }
|
||||
return node;
|
||||
}).length;
|
||||
});
|
||||
}).then(() => {
|
||||
const stanza = $iq({
|
||||
'from': _converse.bare_jid,
|
||||
'id': iq_stanza.getAttribute('id'),
|
||||
'to': _converse.bare_jid,
|
||||
'type': 'result',
|
||||
}).c('pubsub', {
|
||||
'xmlns': 'http://jabber.org/protocol/pubsub'
|
||||
}).c('items', {'node': "eu.siacs.conversations.axolotl.bundles:482886413b977930064a5888b92134fe"})
|
||||
.c('item')
|
||||
.c('bundle', {'xmlns': 'eu.siacs.conversations.axolotl'})
|
||||
.c('signedPreKeyPublic', {'signedPreKeyId': '4223'}).t(btoa('100000')).up()
|
||||
.c('signedPreKeySignature').t(btoa('200000')).up()
|
||||
.c('identityKey').t(btoa('300000')).up()
|
||||
.c('prekeys')
|
||||
.c('preKeyPublic', {'preKeyId': '1'}).t(btoa('1991')).up()
|
||||
.c('preKeyPublic', {'preKeyId': '2'}).t(btoa('1992')).up()
|
||||
.c('preKeyPublic', {'preKeyId': '3'}).t(btoa('1993'));
|
||||
|
||||
spyOn(_converse.connection, 'send').and.callFake(stanza => { sent_stanza = stanza });
|
||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||
@ -117,11 +149,25 @@
|
||||
`<body>This is an OMEMO encrypted message which your client doesn’t seem to support. Find more information on https://conversations.im/omemo</body>`+
|
||||
`<encrypted xmlns='eu.siacs.conversations.axolotl'>`+
|
||||
`<header sid='123456789'>`+
|
||||
`<key>eyJpdiI6IjEyMzQ1In0=</key>`+
|
||||
`<iv>12345</iv>`+
|
||||
`<key rid='482886413b977930064a5888b92134fe'>eyJ0eXBlIjoxLCJib2R5IjoiYzFwaDNSNzNYNyIsInJlZ2lzdHJhdGlvbklkIjoiMTMzNyJ9</key>`+
|
||||
`<key rid='555'>eyJ0eXBlIjoxLCJib2R5IjoiYzFwaDNSNzNYNyIsInJlZ2lzdHJhdGlvbklkIjoiMTMzNyJ9</key>`+
|
||||
`<iv>${sent_stanza.nodeTree.querySelector('iv').textContent}</iv>`+
|
||||
`</header>`+
|
||||
`</encrypted>`+
|
||||
`</message>`);
|
||||
|
||||
// Test reception of an encrypted message
|
||||
const stanza = $msg({
|
||||
'from': contact_jid,
|
||||
'to': _converse.connection.jid,
|
||||
'type': 'chat',
|
||||
'id': 'qwerty'
|
||||
}).c('body').t('This is a fallback message').up()
|
||||
.c('encrypted', {'xmlns': Strophe.NS.OMEMO})
|
||||
.c('header', {'sid': '555'})
|
||||
.c('key', {'rid': _converse.omemo_store.get('device_id')}).t('c1ph3R73X7').up()
|
||||
.c('iv').t('1234');
|
||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||
done();
|
||||
});
|
||||
}));
|
||||
|
@ -92,8 +92,13 @@
|
||||
const { _converse } = this.__super__;
|
||||
return new Promise((resolve, reject) => {
|
||||
_converse.getDevicesForContact(this.get('jid'))
|
||||
.then((devices) => {
|
||||
Promise.all(devices.map((device) => device.getBundle()))
|
||||
.then((their_devices) => {
|
||||
const device_id = _converse.omemo_store.get('device_id'),
|
||||
devicelist = _converse.devicelists.get(_converse.bare_jid),
|
||||
own_devices = devicelist.devices.filter(device => device.get('id') !== device_id),
|
||||
devices = _.concat(own_devices, their_devices.models);
|
||||
|
||||
Promise.all(devices.map(device => device.getBundle()))
|
||||
.then(() => this.buildSessions(devices))
|
||||
.then(() => resolve(devices))
|
||||
.catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||
@ -165,22 +170,27 @@
|
||||
address = new libsignal.SignalProtocolAddress(this.get('jid'), device.get('id')),
|
||||
sessionCipher = new window.libsignal.SessionCipher(_converse.omemo_store, address);
|
||||
|
||||
return sessionCipher.encrypt(plaintext);
|
||||
return new Promise((resolve, reject) => {
|
||||
sessionCipher.encrypt(plaintext)
|
||||
.then(payload => resolve({'payload': payload, 'device': device}))
|
||||
.catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||
});
|
||||
},
|
||||
|
||||
addKeysToMessageStanza (stanza, devices, payloads) {
|
||||
for (var i in payloads) {
|
||||
if (Object.prototype.hasOwnProperty.call(payloads, i)) {
|
||||
const payload = btoa(JSON.stringify(payloads[i]))
|
||||
const prekey = 3 == parseInt(payloads[i].type, 10)
|
||||
if (i == payloads.length-1) {
|
||||
stanza.c('key', {'rid': devices.get('id') }).t(payload)
|
||||
if (prekey) {
|
||||
stanza.attrs({'prekey': prekey});
|
||||
}
|
||||
stanza.up().c('iv').t(payloads[0].iv).up().up()
|
||||
} else {
|
||||
stanza.c('key', {prekey: prekey, rid: devices.get('id') }).t(payload).up()
|
||||
addKeysToMessageStanza (stanza, dicts, iv) {
|
||||
for (var i in dicts) {
|
||||
if (Object.prototype.hasOwnProperty.call(dicts, i)) {
|
||||
const payload = dicts[i].payload,
|
||||
device = dicts[i].device,
|
||||
prekey = 3 == parseInt(payload.type, 10);
|
||||
|
||||
stanza.c('key', {'rid': device.get('id') }).t(btoa(JSON.stringify(dicts[i].payload)));
|
||||
if (prekey) {
|
||||
stanza.attrs({'prekey': prekey});
|
||||
}
|
||||
stanza.up();
|
||||
if (i == dicts.length-1) {
|
||||
stanza.c('iv').t(iv).up().up()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,8 +223,13 @@
|
||||
// long-standing SignalProtocol session.
|
||||
|
||||
// TODO: need to include own devices here as well (and filter out distrusted devices)
|
||||
const promises = devices.map(device => this.encryptKey(payload.key_str+payload.tag, device));
|
||||
return Promise.all(promises).then((payloads) => this.addKeysToMessageStanza(stanza, devices, payloads));
|
||||
const promises = devices
|
||||
.filter(device => device.get('trusted') != UNTRUSTED)
|
||||
.map(device => this.encryptKey(payload.key_str+payload.tag, device));
|
||||
|
||||
return Promise.all(promises)
|
||||
.then((dicts) => this.addKeysToMessageStanza(stanza, dicts, payload.iv))
|
||||
.catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -16,7 +16,9 @@
|
||||
this.remoteAddress = remote_address;
|
||||
this.storage = storage;
|
||||
this.encrypt = () => Promise.resolve({
|
||||
'iv': '12345'
|
||||
'type': 1,
|
||||
'body': 'c1ph3R73X7',
|
||||
'registrationId': '1337'
|
||||
});
|
||||
},
|
||||
'SessionBuilder': function (storage, remote_address) {
|
||||
|
Loading…
Reference in New Issue
Block a user