diff --git a/lib/client.js b/lib/client.js index f72a13583..d0bb42443 100644 --- a/lib/client.js +++ b/lib/client.js @@ -377,14 +377,13 @@ MatrixClient.prototype.isEventSenderVerified = function(event) { return false; } - var cryptoContent = event.getWireContent(); - var sender_key = cryptoContent.sender_key; + var sender_key = event.getSenderKey(); if (!sender_key) { return false; } - var algorithm = cryptoContent.algorithm; + var algorithm = event.getWireContent().algorithm; return this._crypto.isSenderKeyVerified( event.getSender(), algorithm, sender_key @@ -418,6 +417,20 @@ function onCryptoEvent(client, event) { } } +/** + * handle a room key event + * + * @private + * + * @param {MatrixEvent} event + */ +MatrixClient.prototype._onRoomKeyEvent = function(event) { + if (!this._crypto) { + return; + } + this._crypto.onRoomKeyEvent(event); +}; + /** * Enable end-to-end encryption for a room. * @param {string} roomId The room ID to enable encryption in. @@ -2628,7 +2641,15 @@ function _PojoToMatrixEventMapper(client) { if (plainOldJsObject.type === "m.room.encrypted") { clearData = _decryptMessage(client, plainOldJsObject); } - return new MatrixEvent(plainOldJsObject, clearData); + var matrixEvent = new MatrixEvent(plainOldJsObject, clearData); + + // XXXX massive hack to deal with the fact that megolm keys are in the + // room for now, and we need to handle them before attempting to + // decrypt the following megolm messages. + if (matrixEvent.getType() == "m.room_key") { + client._onRoomKeyEvent(matrixEvent); + } + return matrixEvent; } return mapper; } diff --git a/lib/crypto-algorithms/base.js b/lib/crypto-algorithms/base.js index 14c6ba18c..83a615fcb 100644 --- a/lib/crypto-algorithms/base.js +++ b/lib/crypto-algorithms/base.js @@ -95,12 +95,16 @@ EncryptionAlgorithm.prototype.initRoomEncryption = function(roomMembers) { * base type for decryption implementations * * @constructor + * @alias module:crypto-algorithms/base.DecryptionAlgorithm + * * @param {object} params parameters * @param {module:OlmDevice} params.olmDevice olm.js wrapper */ -module.exports.DecryptionAlgorithm = function(params) { +var DecryptionAlgorithm = function(params) { this._olmDevice = params.olmDevice; }; +/** */ +module.exports.DecryptionAlgorithm = DecryptionAlgorithm; /** * Decrypt an event @@ -116,6 +120,17 @@ module.exports.DecryptionAlgorithm = function(params) { * problem decrypting the event */ +/** + * Handle a key event + * + * @method module:crypto-algorithms/base.DecryptionAlgorithm#onRoomKeyEvent + * + * @param {module:modules/event~MatrixEvent} event key event + */ +DecryptionAlgorithm.prototype.onRoomKeyEvent = function(params) { + // ignore by default +}; + /** * Exception thrown when decryption fails * diff --git a/lib/crypto-algorithms/megolm.js b/lib/crypto-algorithms/megolm.js index 908b0e623..e74e36e6e 100644 --- a/lib/crypto-algorithms/megolm.js +++ b/lib/crypto-algorithms/megolm.js @@ -65,16 +65,6 @@ MegolmEncryption.prototype._ensureOutboundSession = function(room) { var session_id = this._olmDevice.createOutboundGroupSession(); var key = this._olmDevice.getOutboundGroupSessionKey(session_id); - console.log( - 'Created outbound session. Add with window.mxMatrixClientPeg.' + - 'matrixClient._crypto._olmDevice.addInboundGroupSession("' + - [ - this._roomId, this._olmDevice.deviceCurve25519Key, session_id, - key.key, key.chain_index - ].join('", "') + - '")' - ); - this._olmDevice.addInboundGroupSession( this._roomId, this._olmDevice.deviceCurve25519Key, session_id, key.key, key.chain_index @@ -244,6 +234,30 @@ MegolmDecryption.prototype.decryptEvent = function(event) { } }; +/** + * @inheritdoc + * + * @param {module:modules/event~MatrixEvent} event key event + */ +MegolmDecryption.prototype.onRoomKeyEvent = function(event) { + console.log("Adding key from ", event); + var content = event.getContent(); + + if (!content.room_id || + !content.session_id || + !content.session_key || + content.chain_index === undefined + ) { + console.error("key event is missing fields"); + return; + } + + this._olmDevice.addInboundGroupSession( + content.room_id, event.getSenderKey(), content.session_id, + content.session_key, content.chain_index + ); +}; + base.registerAlgorithm( olmlib.MEGOLM_ALGORITHM, MegolmEncryption, MegolmDecryption ); diff --git a/lib/crypto.js b/lib/crypto.js index f070f0df5..68aca21ff 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -728,6 +728,26 @@ Crypto.prototype.decryptEvent = function(event) { return alg.decryptEvent(event); }; + +/** + * Handle a key event + * + * @param {module:modules/event~MatrixEvent} event key event + */ +Crypto.prototype.onRoomKeyEvent = function(event) { + var content = event.getContent(); + var AlgClass = algorithms.DECRYPTION_CLASSES[content.algorithm]; + if (!AlgClass) { + throw new algorithms.DecryptionError( + "Unable to handle keys for " + content.algorithm + ); + } + var alg = new AlgClass({ + olmDevice: this._olmDevice, + }); + alg.onRoomKeyEvent(event); +}; + /** * @see module:crypto-algorithms/base.DecryptionError */ diff --git a/lib/models/event.js b/lib/models/event.js index f7c915399..33ba03e72 100644 --- a/lib/models/event.js +++ b/lib/models/event.js @@ -232,6 +232,14 @@ module.exports.MatrixEvent.prototype = { return Boolean(this._clearEvent.type); }, + getSenderKey: function() { + if (!this.isEncrypted()) { + return null; + } + var c = this.getWireContent(); + return c.sender_key; + }, + getUnsigned: function() { return this.event.unsigned || {}; },