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
Refactor device key upload
Use another-json instead of awful manual json building. Sign the device keys at the point of upload, instead of having to keep the signed string in memory. Only upload device keys once (they are correctly merged with the one-time keys by synapse).
This commit is contained in:
@@ -24,6 +24,7 @@ var PushProcessor = require('./pushprocessor');
|
||||
var EventEmitter = require("events").EventEmitter;
|
||||
var q = require("q");
|
||||
var url = require('url');
|
||||
var anotherjson = require('another-json');
|
||||
|
||||
var httpApi = require("./http-api");
|
||||
var MatrixEvent = require("./models/event").MatrixEvent;
|
||||
@@ -126,31 +127,24 @@ function MatrixClient(opts) {
|
||||
};
|
||||
|
||||
this._olmDevice = null;
|
||||
this._cryptoAlgorithms = [];
|
||||
|
||||
if (CRYPTO_ENABLED && this.sessionStore !== null && userId !== null &&
|
||||
this.deviceId !== null) {
|
||||
this._olmDevice = new OlmDevice(opts.sessionStore);
|
||||
this._cryptoAlgorithms.push(OLM_ALGORITHM);
|
||||
|
||||
var json = '{"algorithms":["' + OLM_ALGORITHM + '"]';
|
||||
json += ',"device_id":"' + this.deviceId + '"';
|
||||
json += ',"keys":';
|
||||
json += '{"ed25519:' + this.deviceId + '":';
|
||||
json += JSON.stringify(this._olmDevice.deviceEd25519Key);
|
||||
json += ',"curve25519:' + this.deviceId + '":';
|
||||
json += JSON.stringify(this._olmDevice.deviceCurve25519Key);
|
||||
json += '}';
|
||||
json += ',"user_id":' + JSON.stringify(userId);
|
||||
json += '}';
|
||||
var signature = this._olmDevice.sign(json);
|
||||
this.deviceKeys = JSON.parse(json);
|
||||
var signatures = {};
|
||||
signatures[userId] = {};
|
||||
signatures[userId]["ed25519:" + this.deviceId] = signature;
|
||||
this.deviceKeys.signatures = signatures;
|
||||
// build our device keys: these will later be uploaded
|
||||
this._deviceKeys = {};
|
||||
this._deviceKeys["ed25519:" + this.deviceId] =
|
||||
this._olmDevice.deviceEd25519Key;
|
||||
this._deviceKeys["curve25519:" + this.deviceId] =
|
||||
this._olmDevice.deviceCurve25519Key;
|
||||
|
||||
// add our own deviceinfo to the sessionstore
|
||||
var deviceInfo = {
|
||||
keys: this.deviceKeys.keys,
|
||||
algorithms: this.deviceKeys.algorithms,
|
||||
keys: this._deviceKeys,
|
||||
algorithms: this._cryptoAlgorithms,
|
||||
verified: DeviceVerification.VERIFIED,
|
||||
};
|
||||
var myDevices = this.sessionStore.getEndToEndDevicesForUser(
|
||||
@@ -160,8 +154,10 @@ function MatrixClient(opts) {
|
||||
this.sessionStore.storeEndToEndDevicesForUser(
|
||||
userId, myDevices
|
||||
);
|
||||
|
||||
setupCryptoEventHandler(this);
|
||||
}
|
||||
|
||||
this.scheduler = opts.scheduler;
|
||||
if (this.scheduler) {
|
||||
var self = this;
|
||||
@@ -287,6 +283,9 @@ MatrixClient.prototype.retryImmediately = function() {
|
||||
return this._syncApi.retryImmediately();
|
||||
};
|
||||
|
||||
// Crypto bits
|
||||
// ===========
|
||||
|
||||
/**
|
||||
* Is end-to-end crypto enabled for this client.
|
||||
* @return {boolean} True if end-to-end is enabled.
|
||||
@@ -318,7 +317,7 @@ MatrixClient.prototype.getDeviceEd25519Key = function() {
|
||||
*/
|
||||
MatrixClient.prototype.uploadKeys = function(maxKeys, deferred) {
|
||||
var self = this;
|
||||
return _doKeyUpload(this).then(function(res) {
|
||||
return _uploadDeviceKeys(this).then(function(res) {
|
||||
var keyCount = res.one_time_key_counts.curve25519 || 0;
|
||||
var maxOneTimeKeys = self._olmDevice.maxNumberOfOneTimeKeys();
|
||||
var keyLimit = Math.floor(maxOneTimeKeys / 2);
|
||||
@@ -332,12 +331,42 @@ MatrixClient.prototype.uploadKeys = function(maxKeys, deferred) {
|
||||
}
|
||||
|
||||
self._olmDevice.generateOneTimeKeys(numberToGenerate);
|
||||
return _doKeyUpload(self);
|
||||
return _uploadOneTimeKeys(self);
|
||||
});
|
||||
};
|
||||
|
||||
// build the upload request, and return a promise which resolves to the response
|
||||
function _doKeyUpload(client) {
|
||||
// returns a promise which resolves to the response
|
||||
function _uploadDeviceKeys(client) {
|
||||
if (!client._olmDevice) {
|
||||
return q.reject(new Error("End-to-end encryption disabled"));
|
||||
}
|
||||
|
||||
var userId = client.credentials.userId;
|
||||
var deviceId = client.deviceId;
|
||||
|
||||
var deviceKeys = {
|
||||
algorithms: client._cryptoAlgorithms,
|
||||
device_id: deviceId,
|
||||
keys: client._deviceKeys,
|
||||
user_id: userId,
|
||||
signatures: {},
|
||||
};
|
||||
|
||||
deviceKeys.signatures[userId] = {};
|
||||
deviceKeys.signatures[userId]["ed25519:" + deviceId] =
|
||||
client._olmDevice.sign(anotherjson.stringify(deviceKeys));
|
||||
|
||||
return client.uploadKeysRequest({
|
||||
device_keys: deviceKeys,
|
||||
}, {
|
||||
// for now, we set the device id explicitly, as we may not be using the
|
||||
// same one as used in login.
|
||||
device_id: deviceId,
|
||||
});
|
||||
}
|
||||
|
||||
// returns a promise which resolves to the response
|
||||
function _uploadOneTimeKeys(client) {
|
||||
if (!client._olmDevice) {
|
||||
return q.reject(new Error("End-to-end encryption disabled"));
|
||||
}
|
||||
@@ -350,14 +379,13 @@ function _doKeyUpload(client) {
|
||||
oneTimeJson["curve25519:" + keyId] = oneTimeKeys.curve25519[keyId];
|
||||
}
|
||||
}
|
||||
var content = {
|
||||
device_keys: client.deviceKeys,
|
||||
return client.uploadKeysRequest({
|
||||
one_time_keys: oneTimeJson
|
||||
};
|
||||
var path = "/keys/upload/" + client.deviceId;
|
||||
return client._http.authedRequestWithPrefix(
|
||||
undefined, "POST", path, undefined, content, httpApi.PREFIX_UNSTABLE
|
||||
).then(function(res) {
|
||||
}, {
|
||||
// for now, we set the device id explicitly, as we may not be using the
|
||||
// same one as used in login.
|
||||
device_id: client.deviceId,
|
||||
}).then(function(res) {
|
||||
client._olmDevice.markKeysAsPublished();
|
||||
return res;
|
||||
});
|
||||
@@ -474,6 +502,10 @@ function _updateStoredDeviceKeysForUser(userId, userStore, userResult) {
|
||||
deviceStore = userStore[deviceId];
|
||||
|
||||
if (deviceStore.keys["ed25519:" + deviceId] != signKey) {
|
||||
// this should only happen if the list has been MITMed; we are
|
||||
// best off sticking with the original keys.
|
||||
//
|
||||
// Should we warn the user about it somehow?
|
||||
console.warn("Ed25519 key for device" + userId + ": " +
|
||||
deviceId + " has changed");
|
||||
continue;
|
||||
@@ -852,6 +884,7 @@ MatrixClient.prototype.isRoomEncrypted = function(roomId) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the room for the given room ID.
|
||||
* This function will return a valid room for any room for which a Room event
|
||||
|
||||
Reference in New Issue
Block a user