Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send one time key count and unused fallback keys for rust-crypto #3215

Merged

Conversation

florianduros
Copy link
Contributor

@florianduros florianduros commented Mar 14, 2023

Checklist

  • Tests written for new code (and old code if feasible)
  • Linter and other CI checks pass
  • Sign-off given on the changes (see CONTRIBUTING.md)

Fix element-hq/element-web#24795 (comment)


Here's what your changelog entry will look like:

✨ Features

@florianduros florianduros added this pull request to the merge queue Mar 22, 2023
@florianduros florianduros merged commit f795577 into develop Mar 22, 2023
@florianduros florianduros deleted the florianduros/feat/add-oldmachine-missing-parameters branch March 22, 2023 10:45
Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@florianduros thanks for getting this working! it's a great start but there's a few things that need a bit of polish before we can call it done imho.

Comment on lines +108 to +119
/**
* Called by the /sync loop whenever there are incoming to-device messages.
*
* The implementation may preprocess the received messages (eg, decrypt them) and return an
* updated list of messages for dispatch to the rest of the system.
*
* Note that, unlike {@link ClientEvent.ToDeviceEvent} events, this is called on the raw to-device
* messages, rather than the results of any decryption attempts.
*
* @param oneTimeKeysCounts - the received one time key counts
* @returns A list of preprocessed to-device messages.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These doc-comments are inaccurate: these methods aren't doing anything with received messages, nor returning them.

* @param oneTimeKeysCounts - the received one time key counts
* @returns A list of preprocessed to-device messages.
*/
preprocessOneTimeKeyCounts(oneTimeKeysCounts: Map<string, number>): Promise<void>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

preprocess... is not a good name for these methods. "Preprocess" implies there is still some "processing" to be done after the "preprocessing" takes place. You can just use "process" here.

const currentCount = data.device_one_time_keys_count.signed_curve25519 || 0;
this.syncOpts.crypto.updateOneTimeKeyCount(currentCount);
if (data.device_one_time_keys_count) {
const map = new Map<string, number>(Object.entries(data.device_one_time_keys_count));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should leave this conversion into a Map (or Set, below) to the cryptoCallbacks implementation.

Comment on lines +1528 to +1536
this.syncOpts.cryptoCallbacks?.preprocessOneTimeKeyCounts(map);
}
if (
this.syncOpts.crypto &&
(data.device_unused_fallback_key_types || data["org.matrix.msc2732.device_unused_fallback_key_types"])
) {
if (data.device_unused_fallback_key_types || data["org.matrix.msc2732.device_unused_fallback_key_types"]) {
// The presence of device_unused_fallback_key_types indicates that the
// server supports fallback keys. If there's no unused
// signed_curve25519 fallback key we need a new one.
const unusedFallbackKeys =
data.device_unused_fallback_key_types || data["org.matrix.msc2732.device_unused_fallback_key_types"];
this.syncOpts.crypto.setNeedsNewFallback(
Array.isArray(unusedFallbackKeys) && !unusedFallbackKeys.includes("signed_curve25519"),
);
this.syncOpts.cryptoCallbacks?.preprocessUnusedFallbackKeys(new Set<string>(unusedFallbackKeys || null));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be easier to combine these two methods into one?

this.syncOpts.cryptoCallbacks?.processKeyCounts(data.device_one_time_keys_count, data.device_unused_fallback_key_types ?? data["org.matrix.msc2732.device_unused_fallback_key_types"]);

Comment on lines -1526 to 1537
if (this.syncOpts.crypto && data.device_one_time_keys_count) {
const currentCount = data.device_one_time_keys_count.signed_curve25519 || 0;
this.syncOpts.crypto.updateOneTimeKeyCount(currentCount);
if (data.device_one_time_keys_count) {
const map = new Map<string, number>(Object.entries(data.device_one_time_keys_count));
this.syncOpts.cryptoCallbacks?.preprocessOneTimeKeyCounts(map);
}
if (
this.syncOpts.crypto &&
(data.device_unused_fallback_key_types || data["org.matrix.msc2732.device_unused_fallback_key_types"])
) {
if (data.device_unused_fallback_key_types || data["org.matrix.msc2732.device_unused_fallback_key_types"]) {
// The presence of device_unused_fallback_key_types indicates that the
// server supports fallback keys. If there's no unused
// signed_curve25519 fallback key we need a new one.
const unusedFallbackKeys =
data.device_unused_fallback_key_types || data["org.matrix.msc2732.device_unused_fallback_key_types"];
this.syncOpts.crypto.setNeedsNewFallback(
Array.isArray(unusedFallbackKeys) && !unusedFallbackKeys.includes("signed_curve25519"),
);
this.syncOpts.cryptoCallbacks?.preprocessUnusedFallbackKeys(new Set<string>(unusedFallbackKeys || null));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we also need to do this for sliding-sync-sdk.ts, by the way.

Comment on lines +1920 to +1922
{
overwriteRoutes: true,
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we overwriteRoutes here? it could do with a comment at least.

Comment on lines +1917 to +1930
fetchMock.post(
new URL("/_matrix/client/r0/keys/upload", aliceClient.getHomeserverUrl()).toString(),
listener,
{
overwriteRoutes: true,
},
);
fetchMock.post(
new URL("/_matrix/client/v3/keys/upload", aliceClient.getHomeserverUrl()).toString(),
listener,
{
overwriteRoutes: true,
},
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe to avoid the repetition here, do for (const path in ["/_matrix/client/r0/keys/upload", "/_matrix/client/v3/keys/upload"]).

Comment on lines +1934 to +1957
it("should make key upload request after sync", async () => {
let uploadPromise = listenToUpload();
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
await startClientAndAwaitFirstSync();

syncResponder.sendOrQueueSyncResponse(getSyncResponse([]));

await syncPromise(aliceClient);
expect(await uploadPromise).toBeGreaterThan(0);

uploadPromise = listenToUpload();
syncResponder.sendOrQueueSyncResponse({
next_batch: 2,
device_one_time_keys_count: { signed_curve25519: 0 },
});

// Advance local date to 2 minutes
// The old crypto only runs the upload every 60 seconds
jest.setSystemTime(Date.now() + 2 * 60 * 1000);

await syncPromise(aliceClient);

expect(await uploadPromise).toBeGreaterThan(0);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could probably do with a test for the fallback keys too.

Comment on lines +1909 to +1913
return {
one_time_key_counts: {
signed_curve25519: keysCount ? 60 : keysCount,
},
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's going on here? how did we pick these numbers? why does it depend on keysCount? add some comments please!

Comment on lines +1935 to +1956
let uploadPromise = listenToUpload();
expectAliceKeyQuery({ device_keys: { "@alice:localhost": {} }, failures: {} });
await startClientAndAwaitFirstSync();

syncResponder.sendOrQueueSyncResponse(getSyncResponse([]));

await syncPromise(aliceClient);
expect(await uploadPromise).toBeGreaterThan(0);

uploadPromise = listenToUpload();
syncResponder.sendOrQueueSyncResponse({
next_batch: 2,
device_one_time_keys_count: { signed_curve25519: 0 },
});

// Advance local date to 2 minutes
// The old crypto only runs the upload every 60 seconds
jest.setSystemTime(Date.now() + 2 * 60 * 1000);

await syncPromise(aliceClient);

expect(await uploadPromise).toBeGreaterThan(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could do with some more comments imho. What is going on, what are we checking for?

@florianduros florianduros mentioned this pull request Mar 23, 2023
3 tasks
florianduros added a commit that referenced this pull request Apr 5, 2023
* Improve key upload request

* Add fallback keys check

* Review fixes

* Add comments about sliding sync usage of `processKeyCounts`

* Review fixes

* Better wording
su-ex added a commit to SchildiChat/matrix-js-sdk that referenced this pull request Apr 21, 2023
* Allow via_servers property in findPredecessor (update to MSC3946) ([\matrix-org#3240](matrix-org#3240)). Contributed by @andybalaam.
* Fire `closed` event when IndexedDB closes unexpectedly ([\matrix-org#3218](matrix-org#3218)).
* Implement MSC3952: intentional mentions ([\matrix-org#3092](matrix-org#3092)). Fixes element-hq/element-web#24376.
* Send one time key count and unused fallback keys for rust-crypto ([\matrix-org#3215](matrix-org#3215)). Fixes element-hq/element-web#24795. Contributed by @florianduros.
* Improve `processBeaconEvents` hotpath ([\matrix-org#3200](matrix-org#3200)).
* Implement MSC3966: a push rule condition to check if an array contains a value ([\matrix-org#3180](matrix-org#3180)).
* indexddb-local-backend - return the current sync to database promise … ([\matrix-org#3222](matrix-org#3222)). Contributed by @texuf.
* Revert "Add the call object to Call events" ([\matrix-org#3236](matrix-org#3236)).
* Handle group call redaction ([\matrix-org#3231](matrix-org#3231)). Fixes vector-im/voip-internal#128.
* Stop doing O(n^2) work to find event's home (`eventShouldLiveIn`) ([\matrix-org#3227](matrix-org#3227)). Contributed by @jryans.
* Fix bug where video would not unmute if it started muted ([\matrix-org#3213](matrix-org#3213)). Fixes element-hq/element-call#925.
* Fixes to event encryption in the Rust Crypto implementation ([\matrix-org#3202](matrix-org#3202)).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Element-R: Wire up remaining bits of /sync response
3 participants