diff --git a/lib/crypto/OlmDevice.js b/lib/crypto/OlmDevice.js index 01a710580..a4d564362 100644 --- a/lib/crypto/OlmDevice.js +++ b/lib/crypto/OlmDevice.js @@ -514,21 +514,23 @@ OlmDevice.prototype.getOutboundGroupSessionKey = function(sessionId) { * store an InboundGroupSession in the session store * * @param {string} roomId - * @param {string} senderKey + * @param {string} senderCurve25519Key * @param {string} sessionId * @param {Olm.InboundGroupSession} session + * @param {object} keysClaimed Other keys the sender claims. * @private */ OlmDevice.prototype._saveInboundGroupSession = function( - roomId, senderKey, sessionId, session + roomId, senderCurve25519Key, sessionId, session, keysClaimed ) { var r = { room_id: roomId, session: session.pickle(this._pickleKey), + keysClaimed: keysClaimed, }; this._sessionStore.storeEndToEndInboundGroupSession( - senderKey, sessionId, JSON.stringify(r) + senderKey, senderCurve25519Key, sessionId, JSON.stringify(r) ); }; @@ -569,7 +571,12 @@ OlmDevice.prototype._getInboundGroupSession = function( var session = new Olm.InboundGroupSession(); try { session.unpickle(this._pickleKey, r.session); - return {sessionExists: true, result: func(session)}; + return { + sessionExists: true, + result: func(session), + keysProved: {curve25519: senderKey}, + keysClaimed: r.keysClaimed || {}, + }; } finally { session.free(); } diff --git a/lib/crypto/algorithms/megolm.js b/lib/crypto/algorithms/megolm.js index 78bafdffd..d082ecdb3 100644 --- a/lib/crypto/algorithms/megolm.js +++ b/lib/crypto/algorithms/megolm.js @@ -360,7 +360,7 @@ utils.inherits(MegolmDecryption, base.DecryptionAlgorithm); * @param {object} event raw event * * @return {object} object with 'result' key with decrypted payload (with - * properties 'type', 'content') and a 'sessionKey' key. + * properties 'type', 'content') and a 'sessionExists' key. * * @throws {module:crypto/algorithms/base.DecryptionError} if there is a * problem decrypting the event @@ -382,7 +382,8 @@ MegolmDecryption.prototype.decryptEvent = function(event) { event.room_id, content.sender_key, content.session_id, content.ciphertext ); if (res.sessionExists) { - return {result: JSON.parse(res.result), sessionExists: true}; + res.result = JSON.parse(res.result); + return res; } else { return {sessionExists: false}; } @@ -411,7 +412,7 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) { this._olmDevice.addInboundGroupSession( content.room_id, event.getSenderKey(), content.session_id, - content.session_key, content.chain_index + content.session_key, content.chain_index, event.getKeysClaimed() ); }; diff --git a/lib/crypto/algorithms/olm.js b/lib/crypto/algorithms/olm.js index e75877cdf..df889766b 100644 --- a/lib/crypto/algorithms/olm.js +++ b/lib/crypto/algorithms/olm.js @@ -119,6 +119,17 @@ OlmEncryption.prototype.encryptMessage = function(room, eventType, content) { room_id: room.roomId, type: eventType, content: content, + // Include the ED25519 key so that the recipient knows what + // device this message came from. + // We don't need to include the curve25519 key since the + // recipient will already know this from the olm headers. + // When combined with the device keys retrieved from the + // homeserver signed by the ed25519 key this proves that + // the curve25519 key and the ed25519 key are owned by + // the same device. + keys: { + "ed25519": self._olmDevice.deviceEd25519Key + }, } ); }); @@ -200,7 +211,13 @@ OlmDecryption.prototype.decryptEvent = function(event) { // TODO: Check the sender user id matches the sender key. // TODO: check the room_id and fingerprint if (payloadString !== null) { - return {result: JSON.parse(payloadString), sessionExists: true}; + var payload = JSON.parse(payloadString); + return { + result: payload, + sessionExists: true, + keysProved: {curve25519: deviceKey}, + keysClaimed: payload.keys || {} + }; } else { throw new base.DecryptionError("Bad Encrypted Message"); } diff --git a/lib/crypto/index.js b/lib/crypto/index.js index b0a519ff6..e650308f8 100644 --- a/lib/crypto/index.js +++ b/lib/crypto/index.js @@ -823,8 +823,11 @@ Crypto.prototype.decryptEvent = function(event) { olmDevice: this._olmDevice, }); var r = alg.decryptEvent(event); + var payload = r.result; + payload.keysClaimed = r.keysClaimed; + payload.keysProved = r.keysProved; if (r.sessionExists) { - return r.result; + return payload; } else { // We've got a message for a session we don't have. // Maybe the sender forgot to tell us about the session. diff --git a/lib/models/event.js b/lib/models/event.js index 90e8a39b4..859c2b488 100644 --- a/lib/models/event.js +++ b/lib/models/event.js @@ -233,12 +233,27 @@ module.exports.MatrixEvent.prototype = { return Boolean(this._clearEvent.type); }, + /** + * Returns the curve25519 key that sent this event + */ getSenderKey: function() { - if (!this.isEncrypted()) { - return null; - } - var c = this.getWireContent(); - return c.sender_key; + return this.getKeysProved().curve25519 || null; + }, + + /** + * The keys that must have been owned by the sender of this encrypted event. + * @return {object} + */ + getKeysProved: function() { + return this._clearEvent.keysProved || {}; + }, + + /** + * The additional keys the sender of this encrypted event claims to possess + * @return {object} + */ + getKeysClaimed: function() { + return this._clearEvent.keysClaimed || {}; }, getUnsigned: function() {