1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-29 16:43:09 +03:00

Add getKeysProved and getKeysClaimed methods to MatrixEvent.

These list the keys that sender of the event must have ownership
of and the keys of that the sender claims ownership of.

All olm and megolm messages prove ownership of a curve25519 key.
All new olm and megolm message will now claim ownership of a
ed25519 key.

This allows us to detect if an attacker claims ownership of a curve25519
key they don't own when advertising their device keys, because when we
receive an event from the original user it will have a different ed25519 key
to the attackers.
This commit is contained in:
Mark Haines
2016-09-15 16:26:43 +01:00
parent 49a74755a8
commit bde6a171f6
5 changed files with 57 additions and 14 deletions

View File

@@ -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();
}

View File

@@ -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()
);
};

View File

@@ -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");
}

View File

@@ -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.

View File

@@ -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() {