Skip to content

crypto: Add new ClientEvent.ReceivedToDeviceMessage with proper OlmEncryptionInfo support #4891

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

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from

Conversation

BillCarsonFr
Copy link
Member

@BillCarsonFr BillCarsonFr commented Jun 30, 2025

Notes for reviewer:

Since the integration of the rust-sdk it was not possible to tell the difference between a successfully decrypted to-device event and a cleartext one. With matrix-sdk-crypto-wasm 15.0.0, it is now possible.

This replaces #4835. As suggested the ClientEvent.ToDeviceEvent is deprecated in favour of a new ClientEvent.ReceivedToDeviceMessage:

client.on(ClientEvent.ReceivedToDeviceMessage, (message, encryptionInfo) => {
    processedToDeviceResolver.resolve([message, encryptionInfo]);
});

I also updated a bit the deprecated ClientEvent.ToDeviceEvent so that at least the event.isEncrypted is correct. See this commit dfd851f. This is optional though, but I thought that it would be good to at least restore this? (Notice that other broken APIs stay broken getSenderKey(), decryptionFailureReason(), ...).

There is a change that was revealed by this test. Now UTD events are not returned by the preprocessToDeviceMessages. I don't really see a reason to return them? But we could return them as is with a null encryption info

Checklist

  • Tests written for new code (and old code if feasible).
  • New or updated public/exported symbols have accurate TSDoc documentation.
  • Linter and other CI checks pass.
  • Sign-off given on the changes (see CONTRIBUTING.md).

@BillCarsonFr BillCarsonFr force-pushed the valere/crypto/handle_processedToDevice branch from 1b52566 to d37c78f Compare June 30, 2025 13:23
@BillCarsonFr BillCarsonFr force-pushed the valere/crypto/handle_processedToDevice branch from d37c78f to 9819ca1 Compare June 30, 2025 13:29
@BillCarsonFr BillCarsonFr marked this pull request as ready for review June 30, 2025 13:36
@BillCarsonFr BillCarsonFr requested review from a team as code owners June 30, 2025 13:36
@richvdh richvdh changed the title crypto: Add new ClientEvent.ReceivedToDeviceMessage with proper OlmEncryptionInfo support crypto: Add new ClientEvent.ReceivedToDeviceMessage with proper OlmEncryptionInfo support Jul 1, 2025
@richvdh richvdh added T-Enhancement and removed T-Task Tasks for the team like planning labels Jul 1, 2025
@richvdh
Copy link
Member

richvdh commented Jul 1, 2025

Switching this to T-Enhancement so that it shows up in the js-sdk's changelog

Copy link
Member

@andybalaam andybalaam left a comment

Choose a reason for hiding this comment

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

I don't fully understand this, but it looks sensible. I'd like someone with more clue to take a look too.

/**
* Successfully processed to-device message.
*/
export type IToDeviceMessage = IToDeviceEvent;
Copy link
Member

Choose a reason for hiding this comment

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

What is the purpose of this alias? The compiler won't complain if you use the wrong one, right?

Also, what is the difference in meaning between IToDeviceMessage and IToDeviceEvent.

(Also, do we still use I prefix for interfaces?)

Copy link
Member Author

Choose a reason for hiding this comment

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

I am trying to match a bit more the rust sdk terminlogy that uses message and not event for to-device (they don't have event_ids, and other properties compared to events).
Unfortunatly the spec uses a mix of message and event for to-device.
So I kept IToDeviceEvent for the one coming down the sync, and IToDeviceMessage for the one succesfully processed (and decrypted if applicable)

Copy link
Member Author

Choose a reason for hiding this comment

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

I removed it and keep only IToDeviceEvent 7a843ab

if (cancelledKeyVerificationTxns.includes(txnId)) {
toDeviceEvent.flagCancelled();
.forEach(function (processedEvent) {
// For backwards compatibility, we emit the event as a MatrixEvent
Copy link
Member

Choose a reason for hiding this comment

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

Instead of emitting processedEvent? If so, it would help me if you added that to the comment.

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.

Looks good, a few suggestions.

Comment on lines +1094 to +1106
/**
* Fires whenever the SDK receives a new to-device message.
* @param message - The to-device message which caused this event to fire.
* @param encryptionInfo - The encryptionInfo for this message, null if sent in clear.
* @example
* ```
* matrixClient.on("receivedToDeviceMessage", function(message, encryptionInfo){
* var claimed_sender = encryptionInfo ? encryptionInfo.sender : message.sender;
* var isVerified = encryptionInfo ? encryptionInfo.verified : false;
* var type = message.type;
* });
* ```
*/
Copy link
Member

Choose a reason for hiding this comment

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

For the record, this documentation is actually in the wrong place: it should be on ClientEvent.ReceivedToDeviceMessage (which is what the application developer will actually use) rather than on the map entry (which is just here for typescript, really). Have a look at CryptoEvent, which does a better job of this.

Of course, that's true of all the ClientEvents entries, so no need to fix it as part of this PR. Just sharing FYI really.

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -1365,6 +1365,24 @@ export interface OwnDeviceKeys {
curve25519: string;
}

export interface OlmEncryptionInfo {
Copy link
Member

Choose a reason for hiding this comment

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

could you give this type a doc-comment explaining what it represents, please.

Copy link
Member Author

Choose a reason for hiding this comment

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

src/client.ts Outdated
Comment on lines 1107 to 1110
[ClientEvent.ReceivedToDeviceMessage]: (
message: IToDeviceMessage,
encryptionInfo: OlmEncryptionInfo | null,
) => void;
Copy link
Member

Choose a reason for hiding this comment

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

wouldn't it make more sense to use the ReceivedToDeviceMessage type as the payload?

Copy link
Member Author

@BillCarsonFr BillCarsonFr Jul 1, 2025

Choose a reason for hiding this comment

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

I tried that first, but then I changed to use that. Because I thought it was more natural to do like that in javascript? I may be just wrong. I have no strong feeling, will move to use ReceivedToDeviceMessage

src/sync.ts Outdated
@@ -1909,54 +1922,59 @@ export function _createAndReEmitRoom(client: MatrixClient, roomId: string, opts:
/**
* Process a list of (decrypted, where possible) received to-device events.
*
* Converts the events into `MatrixEvent`s, and emits appropriate {@link ClientEvent.ToDeviceEvent} events.
* Converts the to-device message and OlmEncryptionIngo and emits appropriate {@link ClientEvent.ReceivedToDeviceMessage} events.
Copy link
Member

Choose a reason for hiding this comment

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

this sentence doesn't seem to have enough words.

src/sync.ts Outdated
@@ -1909,54 +1922,59 @@ export function _createAndReEmitRoom(client: MatrixClient, roomId: string, opts:
/**
* Process a list of (decrypted, where possible) received to-device events.
*
* Converts the events into `MatrixEvent`s, and emits appropriate {@link ClientEvent.ToDeviceEvent} events.
* Converts the to-device message and OlmEncryptionIngo and emits appropriate {@link ClientEvent.ReceivedToDeviceMessage} events.
* Converts the events into `MatrixEvent`s, and emits the now deprecated {@link ClientEvent.ToDeviceEvent} events for compatibility.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* Converts the events into `MatrixEvent`s, and emits the now deprecated {@link ClientEvent.ToDeviceEvent} events for compatibility.
* Also converts the events into `MatrixEvent`s, and emits the now deprecated {@link ClientEvent.ToDeviceEvent} events for compatibility.

{
const toDeviceEvent = processedEvent.message;
const content = toDeviceEvent.content;
const deprecatedCompatibilityEvent = new MatrixEvent(Object.assign({}, toDeviceEvent));
Copy link
Member

Choose a reason for hiding this comment

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

what is the purpose of the Object.assign here? might be worth adding a comment?

expect(res).toEqual(inputs);
});

it("should pass through bad encrypted messages", async () => {
it("should fail to process bad encrypted messages", async () => {
Copy link
Member

Choose a reason for hiding this comment

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

There is a change that was revealed by this test. Now UTD events are not returned by the preprocessToDeviceMessages. I don't really see a reason to return them?

Agreed.

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.

3 participants