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

Encrypted history sharing: design "key bundle" format #2688

Open
Tracked by #2685
richvdh opened this issue Jan 10, 2025 · 4 comments
Open
Tracked by #2685

Encrypted history sharing: design "key bundle" format #2688

richvdh opened this issue Jan 10, 2025 · 4 comments
Assignees

Comments

@richvdh
Copy link
Member

richvdh commented Jan 10, 2025

Our proposed solution to sharing encrypted room history on invite involves uploading all of the room keys to an encrypted media blob.

This issue tracks the design of a format for that encrypted blob. Likely it will be based on the key export format, but also bear in mind that the key should be autogenerated (rather than derived from a passphrase) and will be shared over a to-device message (see #2689), so see the encrypted attachment format.

We should also consider allowing a way to indicate that a given key was deliberately withheld (eg because the original sender didn't set the "you can reshare it" flag)

We have some ideas for security improvements over the current encrypted attachment format which we should implement too. In particular, we would like to address some of the points raised by the Missing Salamanders blog post. The missing salamanders attack is not relevant to this usecase.

@uhoreg
Copy link
Member

uhoreg commented Feb 24, 2025

Two main options:

Option 1: JSON object with two properties:

  • room_keys: an array of ExportedSessionData objects, except without forwarding_curve_key_chain (since it's useless in this case)
  • withheld: an array of m.room_key.withheld objects, usually with code m.unauthorised to indicate that the recipient isn't allowed to receive the key

Option 2: basically, key export format, but add in "withheld" events. So an array of JSON objects, that have a type field, which can be:

  • m.room_key: an ExportedSessionData object, except without forwarding_curve_key_chain
  • m.room_key.withheld: an m.room_key.withheld object

I'm leaning towards option 1. The idea for option 2 was to have something more compatible with key exports, but it may already be different enough.

Some ideas that I considered:

  • use CBOR or BSON instead of JSON, and send keys as binary instead of base64-encoded. This would decrease the size of the key bundle. However, libolm and vodozemac hand out the keys as base64-encoded strings, which means that applications would need to un-base64 them, which would add complication, so may not be worth it
  • do we also need to send the device keys of the sender, à la MSC4147? Probably not, because the messages will already be marked as untrusted due to being forwarded. Might be helpful for sending keys between a user's own devices, but not for sending between users.

@richvdh
Copy link
Member Author

richvdh commented Feb 25, 2025

AIUI, the difference between your proposals is that Option 1 is an object containing two arrays (ie, splitting the sessions by shared vs withheld) whereas Option 2 combines the two arrays and differentiates the types with a type field.

In both cases, both types of entry contain algorithm, room_id, sender_key and session_id. Room keys additionally contain sender_claimed_keys and session_key; withheld entries additionally contain code and reason.

I'm minded towards option 1 as well, mostly because it means the typing can be stricter.

The idea for option 2 was to have something more compatible with key exports,

What do you mean by this? Why is option 2 more compatible?

@uhoreg
Copy link
Member

uhoreg commented Feb 25, 2025

The idea for option 2 was to have something more compatible with key exports,

What do you mean by this? Why is option 2 more compatible?

So, the thought process was that we start with the key export format (a simple array of ExportedSessionData objects), and then figure out how we can include withheld data. We can add a type field, and then just put withheld events in the same array. The idea was that maybe if the format is similar enough, we could re-use code. But I think the end result is that it's different enough that it doesn't help. And in fact, Option 1 may in fact allow for more code reuse, since the room_keys is (almost) the key export format.

So I don't think that the thought experiment produced anything useful, but I wanted to include it for completeness.

@uhoreg
Copy link
Member

uhoreg commented Feb 25, 2025

Additional thought: for history sharing, all the keys/withheld messages will be for the same room, so we might be able to get away with omitting the room_id properties from the objects (maybe just have a single top-level room_id property) to save some space. However, it might be nice to have the ability in the future to mix different rooms in a single bundle, so we may not want to design out that ability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants