Skip to content

Commit 0b063f6

Browse files
committed
Cache cross-signing private keys if needed on bootstrap
This is a revised version of #1472 which was previously reverted for causing security prompts to appear on device list sync. In this version, we only allow private key requests (which are likely to trigger user dialogs) if we are coming from the bootstrap path. This allows sessions that have already synced cross-signing public keys but never got the private keys for some reason to make forward progress when e.g. the user triggers bootstrap from security settings.
1 parent ed6d4e5 commit 0b063f6

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

spec/unit/crypto/cross-signing.spec.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,9 @@ describe("Cross Signing", function() {
193193
const keyChangePromise = new Promise((resolve, reject) => {
194194
alice.once("crossSigning.keysChanged", async (e) => {
195195
resolve(e);
196-
await alice.checkOwnCrossSigningTrust();
196+
await alice.checkOwnCrossSigningTrust({
197+
allowPrivateKeyRequests: true,
198+
});
197199
});
198200
});
199201

src/crypto/index.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,9 @@ Crypto.prototype.bootstrapCrossSigning = async function({
568568
"Cross-signing private keys not found locally, but they are available " +
569569
"in secret storage, reading storage and caching locally",
570570
);
571-
await this.checkOwnCrossSigningTrust();
571+
await this.checkOwnCrossSigningTrust({
572+
allowPrivateKeyRequests: true,
573+
});
572574
}
573575

574576
// Assuming no app-supplied callback, default to storing new private keys in
@@ -1300,13 +1302,19 @@ Crypto.prototype._onDeviceListUserCrossSigningUpdated = async function(userId) {
13001302
* Check the copy of our cross-signing key that we have in the device list and
13011303
* see if we can get the private key. If so, mark it as trusted.
13021304
*/
1303-
Crypto.prototype.checkOwnCrossSigningTrust = async function() {
1305+
Crypto.prototype.checkOwnCrossSigningTrust = async function({
1306+
allowPrivateKeyRequests = false,
1307+
} = {}) {
13041308
const userId = this._userId;
13051309

13061310
// Before proceeding, ensure our cross-signing public keys have been
13071311
// downloaded via the device list.
13081312
await this.downloadKeys([this._userId]);
13091313

1314+
// Also check which private keys are locally cached.
1315+
const crossSigningPrivateKeys =
1316+
await this._crossSigningInfo.getCrossSigningKeysFromCache();
1317+
13101318
// If we see an update to our own master key, check it against the master
13111319
// key we have and, if it matches, mark it as verified
13121320

@@ -1324,6 +1332,11 @@ Crypto.prototype.checkOwnCrossSigningTrust = async function() {
13241332
const masterChanged = this._crossSigningInfo.getId() !== seenPubkey;
13251333
if (masterChanged) {
13261334
logger.info("Got new master public key", seenPubkey);
1335+
}
1336+
if (
1337+
allowPrivateKeyRequests &&
1338+
(masterChanged || !crossSigningPrivateKeys.has("master"))
1339+
) {
13271340
logger.info("Attempting to retrieve cross-signing master private key");
13281341
let signing = null;
13291342
try {
@@ -1352,6 +1365,11 @@ Crypto.prototype.checkOwnCrossSigningTrust = async function() {
13521365

13531366
if (selfSigningChanged) {
13541367
logger.info("Got new self-signing key", newCrossSigning.getId("self_signing"));
1368+
}
1369+
if (
1370+
allowPrivateKeyRequests &&
1371+
(selfSigningChanged || !crossSigningPrivateKeys.has("self_signing"))
1372+
) {
13551373
logger.info("Attempting to retrieve cross-signing self-signing private key");
13561374
let signing = null;
13571375
try {
@@ -1374,6 +1392,11 @@ Crypto.prototype.checkOwnCrossSigningTrust = async function() {
13741392
}
13751393
if (userSigningChanged) {
13761394
logger.info("Got new user-signing key", newCrossSigning.getId("user_signing"));
1395+
}
1396+
if (
1397+
allowPrivateKeyRequests &&
1398+
(userSigningChanged || !crossSigningPrivateKeys.has("user_signing"))
1399+
) {
13771400
logger.info("Attempting to retrieve cross-signing user-signing private key");
13781401
let signing = null;
13791402
try {

0 commit comments

Comments
 (0)