You've already forked matrix-js-sdk
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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user