Skip to content

Commit

Permalink
Implement sharing of megolm keys
Browse files Browse the repository at this point in the history
  • Loading branch information
richvdh committed Jun 6, 2017
1 parent 70f39ed commit 2c54d76
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 2 deletions.
56 changes: 56 additions & 0 deletions src/crypto/OlmDevice.js
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,62 @@ OlmDevice.prototype.decryptGroupMessage = function(
);
};

/**
* Determine if we have the keys for a given megolm session
*
* @param {string} roomId room in which the message was received
* @param {string} senderKey base64-encoded curve25519 key of the sender
* @param {sring} sessionId session identifier
*
* @returns {boolean} true if we have the keys to this session
*/
OlmDevice.prototype.hasInboundSessionKeys = function(roomId, senderKey, sessionId) {
const s = this._sessionStore.getEndToEndInboundGroupSession(
senderKey, sessionId,
);

if (s === null) {
return false;
}

const r = JSON.parse(s);
if (roomId !== r.room_id) {
console.warn(
`requested keys for inbound group session ${senderKey}|` +
`${sessionId}, with incorrect room_id (expected ${r.room_id}, ` +
`was ${roomId})`,
);
return false;
}

return true;
};

/**
* Extract the keys to a given megolm session, for sharing
*
* @param {string} roomId room in which the message was received
* @param {string} senderKey base64-encoded curve25519 key of the sender
* @param {string} sessionId session identifier
*
* @returns {{chain_index: number, key: string}} details of the session key. The
* key is a base64-encoded megolm key in export format.
*/
OlmDevice.prototype.getInboundGroupSessionKey = function(roomId, senderKey, sessionId) {
function getKey(session, keysClaimed) {
const messageIndex = session.first_known_index();

return {
"chain_index": messageIndex,
"key": session.export_session(messageIndex),
};
}

return this._getInboundGroupSession(
roomId, senderKey, sessionId, getKey,
);
};

/**
* Export an inbound group session
*
Expand Down
4 changes: 2 additions & 2 deletions src/crypto/algorithms/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,11 @@ export {EncryptionAlgorithm}; // https://github.com/jsdoc3/jsdoc/issues/1272
/**
* base type for decryption implementations
*
* @alias module:crypto/algorithms/base.DecryptionAlgorithm
*
* @param {object} params parameters
* @param {string} params.userId The UserID for the local user
* @param {module:crypto} params.crypto crypto core
* @param {module:crypto/OlmDevice} params.olmDevice olm.js wrapper
* @param {module:base-apis~MatrixBaseApis} baseApis base matrix api interface
* @param {string=} params.roomId The ID of the room we will be receiving
* from. Null for to-device events.
*/
Expand All @@ -103,6 +102,7 @@ class DecryptionAlgorithm {
this._userId = params.userId;
this._crypto = params.crypto;
this._olmDevice = params.olmDevice;
this._baseApis = params.baseApis;
this._roomId = params.roomId;
}

Expand Down
83 changes: 83 additions & 0 deletions src/crypto/algorithms/megolm.js
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,89 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
};


MegolmDecryption.prototype.hasKeysForKeyRequest = function(keyRequest) {
const body = keyRequest.requestBody;

return this._olmDevice.hasInboundSessionKeys(
body.room_id,
body.sender_key,
body.session_id,
// TODO: ratchet index
);
};


MegolmDecryption.prototype.shareKeysWithDevice = function(keyRequest) {
const userId = keyRequest.userId;
const deviceId = keyRequest.deviceId;
const deviceInfo = this._crypto.getStoredDevice(userId, deviceId);
const body = keyRequest.requestBody;

olmlib.ensureOlmSessionsForDevices(
this._olmDevice, this._baseApis, {
[userId]: [deviceInfo],
},
).then((devicemap) => {
const olmSessionResult = devicemap[userId][deviceId];
if (!olmSessionResult.sessionId) {
// no session with this device, probably because there
// were no one-time keys.
//
// ensureOlmSessionsForUsers has already done the logging,
// so just skip it.
return;
}

console.log(
"sharing keys for session " + body.sender_key + "|"
+ body.session_id + " with device "
+ userId + ":" + deviceId,
);

const key = this._olmDevice.getInboundGroupSessionKey(
body.room_id, body.sender_key, body.session_id,
);

const payload = {
type: "m.forwarded_room_key",
content: {
algorithm: olmlib.MEGOLM_ALGORITHM,
room_id: body.room_id,
sender_key: body.sender_key,
session_id: body.session_id,
session_key: key.key,
chain_index: key.chain_index,
},
};

const encryptedContent = {
algorithm: olmlib.OLM_ALGORITHM,
sender_key: this._olmDevice.deviceCurve25519Key,
ciphertext: {},
};

olmlib.encryptMessageForDevice(
encryptedContent.ciphertext,
this._userId,
this._deviceId,
this._olmDevice,
userId,
deviceInfo,
payload,
);

const contentMap = {
[userId]: {
[deviceId]: encryptedContent,
},
};

// TODO: retries
return this._baseApis.sendToDevice("m.room.encrypted", contentMap);
}).done();
};


/**
* @inheritdoc
*
Expand Down
1 change: 1 addition & 0 deletions src/crypto/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,7 @@ Crypto.prototype._getRoomDecryptor = function(roomId, algorithm) {
userId: this._userId,
crypto: this,
olmDevice: this._olmDevice,
baseApis: this._baseApis,
roomId: roomId,
});

Expand Down

0 comments on commit 2c54d76

Please sign in to comment.