You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-12-08 19:08:34 +03:00
Cross sign the current device with the SSK
whenever we get the SSK, ie. when creating or restoring a backup
This commit is contained in:
@@ -1594,6 +1594,12 @@ MatrixBaseApis.prototype.uploadKeysRequest = function(content, opts, callback) {
|
||||
);
|
||||
};
|
||||
|
||||
MatrixBaseApis.prototype.uploadKeySignatures = function(content) {
|
||||
return this._http.authedRequestWithPrefix(
|
||||
undefined, "POST", '/keys/signatures/upload', undefined, content, httpApi.PREFIX_UNSTABLE,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Download device keys
|
||||
*
|
||||
|
||||
@@ -1070,8 +1070,10 @@ MatrixClient.prototype.createKeyBackupVersion = function(info, auth, replacesSsk
|
||||
};
|
||||
|
||||
return this._cryptoStore.doTxn('readwrite', [IndexedDBCryptoStore.STORE_ACCOUNT], (txn) => {
|
||||
// store the newly generated account keys
|
||||
this._cryptoStore.storeAccountKeys(txn, info.accountKeys);
|
||||
}).then(() => {
|
||||
// upload the public part of the account keys
|
||||
return this.uploadDeviceSigningKeys(keys);
|
||||
}).then(() => {
|
||||
return this._crypto._signObject(data.auth_data);
|
||||
@@ -1086,6 +1088,9 @@ MatrixClient.prototype.createKeyBackupVersion = function(info, auth, replacesSsk
|
||||
version: res.version,
|
||||
});
|
||||
return res;
|
||||
}).then(() => {
|
||||
// upload signatures between the SSK & this device
|
||||
return this._crypto.uploadDeviceKeySignatures();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1199,8 +1204,6 @@ MatrixClient.prototype._restoreKeyBackup = async function(
|
||||
let totalKeyCount = 0;
|
||||
let keys = [];
|
||||
|
||||
const path = this._makeKeyBackupPath(targetRoomId, targetSessionId, backupInfo.version);
|
||||
|
||||
const decryption = new global.Olm.PkDecryption();
|
||||
try {
|
||||
decryption.init_with_private_key(privKey);
|
||||
@@ -1237,9 +1240,14 @@ MatrixClient.prototype._restoreKeyBackup = async function(
|
||||
throw e;
|
||||
}
|
||||
|
||||
return this._http.authedRequest(
|
||||
undefined, "GET", path.path, path.queryData,
|
||||
).then((res) => {
|
||||
// start by signing this device from the SSK now we have it
|
||||
return this._crypto.uploadDeviceKeySignatures().then(() => {
|
||||
// Now fetch the encrypted keys
|
||||
const path = this._makeKeyBackupPath(targetRoomId, targetSessionId, backupInfo.version);
|
||||
return this._http.authedRequest(
|
||||
undefined, "GET", path.path, path.queryData,
|
||||
);
|
||||
}).then((res) => {
|
||||
if (res.rooms) {
|
||||
for (const [roomId, roomData] of Object.entries(res.rooms)) {
|
||||
if (!roomData.sessions) continue;
|
||||
|
||||
@@ -46,6 +46,8 @@ import {
|
||||
newUnknownMethodError,
|
||||
} from './verification/Error';
|
||||
|
||||
import { pkSign } from './PkSigning';
|
||||
|
||||
const defaultVerificationMethods = {
|
||||
[ScanQRCode.NAME]: ScanQRCode,
|
||||
[ShowQRCode.NAME]: ShowQRCode,
|
||||
@@ -457,8 +459,20 @@ Crypto.prototype.uploadDeviceKeys = function() {
|
||||
user_id: userId,
|
||||
};
|
||||
|
||||
let accountKeys;
|
||||
return crypto._signObject(deviceKeys).then(() => {
|
||||
crypto._baseApis.uploadKeysRequest({
|
||||
return this._cryptoStore.doTxn('readonly', [IndexedDBCryptoStore.STORE_ACCOUNT], (txn) => {
|
||||
this._cryptoStore.getAccountKeys(txn, keys => {
|
||||
accountKeys = keys;
|
||||
});
|
||||
});
|
||||
}).then(() => {
|
||||
if (accountKeys && accountKeys.self_signing_key_seed) {
|
||||
// if we have an SSK, sign the key with the SSK too
|
||||
pkSign(deviceKeys, Buffer.from(accountKeys.self_signing_key_seed, 'base64'), userId);
|
||||
}
|
||||
|
||||
return crypto._baseApis.uploadKeysRequest({
|
||||
device_keys: deviceKeys,
|
||||
}, {
|
||||
// for now, we set the device id explicitly, as we may not be using the
|
||||
@@ -468,6 +482,45 @@ Crypto.prototype.uploadDeviceKeys = function() {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* If a self-signing key is available, uploads the signature of this device from
|
||||
* the self-signing key
|
||||
*
|
||||
* @return {bool} Promise: True if signatures were uploaded or otherwise false
|
||||
* (eg. if no account keys were available)
|
||||
*/
|
||||
Crypto.prototype.uploadDeviceKeySignatures = async function() {
|
||||
const crypto = this;
|
||||
const userId = crypto._userId;
|
||||
const deviceId = crypto._deviceId;
|
||||
|
||||
const thisDeviceKey = {
|
||||
algorithms: crypto._supportedAlgorithms,
|
||||
device_id: deviceId,
|
||||
keys: crypto._deviceKeys,
|
||||
user_id: userId,
|
||||
};
|
||||
let accountKeys;
|
||||
await this._cryptoStore.doTxn('readonly', [IndexedDBCryptoStore.STORE_ACCOUNT], (txn) => {
|
||||
this._cryptoStore.getAccountKeys(txn, keys => {
|
||||
accountKeys = keys;
|
||||
});
|
||||
});
|
||||
if (!accountKeys || !accountKeys.self_signing_key_seed) return false;
|
||||
|
||||
// Sign this device with the SSK
|
||||
pkSign(thisDeviceKey, Buffer.from(accountKeys.self_signing_key_seed, 'base64'), userId);
|
||||
|
||||
const content = {
|
||||
[userId]: {
|
||||
[deviceId]: thisDeviceKey,
|
||||
},
|
||||
};
|
||||
|
||||
await crypto._baseApis.uploadKeySignatures(content);
|
||||
return true
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores the current one_time_key count which will be handled later (in a call of
|
||||
* onSyncCompleted). The count is e.g. coming from a /sync response.
|
||||
|
||||
Reference in New Issue
Block a user