Skip to content

Encrypted history sharing: design to-device message format #2689

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

Closed
richvdh opened this issue Jan 10, 2025 · 7 comments
Closed

Encrypted history sharing: design to-device message format #2689

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

Comments

@richvdh
Copy link
Member

richvdh commented Jan 10, 2025

Our proposed solution to sharing encrypted room history on invite involves sharing the keys to an encrypted blob via to-device messages.

This issue tracks the creation of a format for those to-device messages. Likely they will be based on the encrypted attachment format.

Conclusion

2025-04-11: for reference, the current design for this is:

{
  "type": "m.room_key_bundle", // or "io.element.msc4268.room_key_bundle" while unstable
  "content": {
    // The room that these are the keys for (we need this so we can download the file at the right time)
    "room_id": "!abc:def",
    // `EncryptedFile` from the encrypted attachment format (https://spec.matrix.org/v1.13/client-server-api/#extensions-to-mroommessage-msgtypes)
    "file": {
      "v": "v2",
      "url": "mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe",     
      "key": {
          "alg": "A256CTR",
          "ext": true,
          "k": "aWF6-32KGYaC3A_FEUCk1Bt0JA37zP0wrStgmdCaW-0",
          "key_ops": ["encrypt","decrypt"],
          "kty": "oct"
      },
      "iv": "w+sE15fzSc0AAAAAAAAAAA",
      "hashes": {
        "sha256": "fdSLu/YkRx3Wyh3KQabP3rd6+SFiKg5lsJZQHtkSAYA"
      }
    }
  }
}
@richvdh
Copy link
Member Author

richvdh commented Jan 10, 2025

(We considered incorporating some security improvements to fix issues highlighted in Lotte's blog post. However, those attacks seem even harder to exploit in this application than in regular encrypted media, so that remains TBD)

@richvdh
Copy link
Member Author

richvdh commented Feb 24, 2025

As a first pass on this, I think all we really need is a to-device message with a property of type EncryptedFile, as defined at https://spec.matrix.org/v1.13/client-server-api/#extensions-to-mroommessage-msgtypes.

I don't think we need the room ID -- that is part of the bundle, and omitting it leaves future flexibility in bundling keys for multiple rooms.

However, I'd like to take the opportunity to simplify the EncryptedFile type to not use JWKs: currently, we have several useless properties, which are opportunities for divergence between implementations. We might as well flatten the hashes too. Even though we may not end up using encrypted media for history sharing, there's enough of a chance that this will work its way into production that I'd rather take the opportunity now to fix it up.

So, example message:

{
  "type": "m.room_key_bundle", // or "io.element.msc4268.room_key_bundle" while unstable
  "content": {
    "file": {
      "v": "v3",
      "url": "mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe",
      "key": "aWF6-32KGYaC3A_FEUCk1Bt0JA37zP0wrStgmdCaW-0",
      "iv": "w+sE15fzSc0AAAAAAAAAAA",
      "hash": "fdSLu/YkRx3Wyh3KQabP3rd6+SFiKg5lsJZQHtkSAYA"
    }
  }
}

As with encrypted media, the sender:

  • Generates a crypto-random 256-bit key to be used as an AES key
  • Generates a crypto-random 64-bit value to be used as the top half of a 128-bit AES-CTR counter block.
  • Encrypts the key bundle (of format to be determined by Encrypted history sharing: design "key bundle" format #2688) using CTR
  • Hashes the ciphertext using sha256.
  • Uploads the encrypted blob as a media item.

Properties of the file property:

Property Type Description
v string Required. Version of the encrypted attachments protocol. Must be v3 for use with m.room_key_bundle.
url string Required. An MXC URI containing the path to an encrypted blob containing the key bundle
key string Required. The 256-bit AES-CTR key, encoded as regular unpadded base64.
iv string Required. The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64. The bottom 64 bits must be zero.
hash string Required. The hash of the ciphertext, using sha256.

Obviously, any messages not matching any of the above requirements should be ignored.

@uhoreg
Copy link
Member

uhoreg commented Feb 24, 2025

I thought about this briefly (because I missed that this was a separate issue from #2688).

I was wondering if we should be leaning into extensible events (matrix-org/matrix-spec-proposals#3551) -- the main difference from your proposed format being that we use m.file as the property name rather than file.

I was also wondering if we wanted to change the encryption from AES to ChaCha20-Poly1305, which is now being used in dehydrated devices and (IIRC) QR code login. My initial thought was to hold off until we do a general update on encrypted media, but if you're proposing to bump the encrypted attachment version, then we may want to consider changing the encryption algorithm as well. (This would also allow us to drop the hash, since it's already authenticated. Also get rid of the "bottom 64 bits must be zero" requirement.)

With respect to the key property, what do you mean by "regular" unpadded base64?

@richvdh
Copy link
Member Author

richvdh commented Feb 24, 2025

I was wondering if we should be leaning into extensible events (matrix-org/matrix-spec-proposals#3551) -- the main difference from your proposed format being that we use m.file as the property name rather than file.

I guess we could. I feel like this message shouldn't be extensible, though -- if the receiving client doesn't understand it, it shouldn't be doing anything else with it, least of all trying to display it as a text file (as you might, given m.file). And I'm not sure that there's any benefit from using the same property name. (Maybe it would be better if we used a completely different name -- bundle_file or something.)

I was also wondering if we wanted to change the encryption from AES to ChaCha20-Poly1305, which is now being used in dehydrated devices and (IIRC) QR code login. My initial thought was to hold off until we do a general update on encrypted media, but if you're proposing to bump the encrypted attachment version, then we may want to consider changing the encryption algorithm as well. (This would also allow us to drop the hash, since it's already authenticated. Also get rid of the "bottom 64 bits must be zero" requirement.)

Yeah, we should. Good idea.

I think that would still mean that key is 256 bits. iv is replaced by nonce, which is 96 bits.

With respect to the key property, what do you mean by "regular" unpadded base64?

I mean not url-safe, for consistency with almost all our other base64 properties; unlike the k property in today's encrypted attachments.

@uhoreg
Copy link
Member

uhoreg commented Feb 24, 2025

I guess we could. I feel like this message shouldn't be extensible, though -- if the receiving client doesn't understand it, it shouldn't be doing anything else with it, least of all trying to display it as a text file (as you might, given m.file). And I'm not sure that there's any benefit from using the same property name. (Maybe it would be better if we used a completely different name -- bundle_file or something.)

I wasn't intending that the message should be extensible. But the format seems like it kind of fits into the extensible events paradigm, in that it's an event of one type, using a format defined by a different type. On the other hand, I'm not sure how much extensible events (and the m.file type in particular) are ready for use. Anyways, it was more of a wondering whether we should do this, rather than a suggestion that we should do it.

@richvdh
Copy link
Member Author

richvdh commented Feb 25, 2025

On further consideration: redesigning encrypted attachments is a bigger job, and fairly clearly out of scope here. I've opened matrix-org/matrix-spec#2087 to track it.

For now then, let's just use the existing encrypted-attachment format for these messages:

{
  "type": "m.room_key_bundle", // or "io.element.msc4268.room_key_bundle" while unstable
  "content": {
    "file": {
      "v": "v2",
      "url": "mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe",     
      "key": {
          "alg": "A256CTR",
          "ext": true,
          "k": "aWF6-32KGYaC3A_FEUCk1Bt0JA37zP0wrStgmdCaW-0",
          "key_ops": ["encrypt","decrypt"],
          "kty": "oct"
      },
      "iv": "w+sE15fzSc0AAAAAAAAAAA",
      "hashes": {
        "sha256": "fdSLu/YkRx3Wyh3KQabP3rd6+SFiKg5lsJZQHtkSAYA"
      }
    }
  }
}

@richvdh richvdh closed this as completed Mar 3, 2025
@richvdh
Copy link
Member Author

richvdh commented Apr 11, 2025

We will also need to include the room_id.

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