End to End Encryption SIG - 2021-12-28


  1. qy

    o/

  2. qy

    Is anyone aware of why session_pre_key_bundle in libomemo-c/libsignal-protocol-c indicates only one prekey, whereas both prekeymessages and bundles in xep-0384 indicate specifically more than one?

  3. moparisthebest

    Which version of 384 are you looking at? The current one no one implements or the previous one that everyone implements?

  4. qy

    Both, tbh

  5. qy

    Afaict so far the main difference is the namespaces

  6. qy

    Ive mainly focused on the axolotl version, since it's more accurate

  7. qy

    I think i see now that only one prekey is used in a signal session, but i still have no clue how to feed an xmpp bundle into libsignal based on that

  8. qy

    Or does libsignal not store bundles themselves?

  9. qy

    Perhaps they remain ephemeral, requested on need, and only sessions are stored?

  10. qy

    My understanding was that bundles were stored too

  11. melvo

    qy: You upload multiple pre keys. A device building a session with your device, takes one of them and calls `session_pre_key_bundle()`. That pre key is passed to `session_pre_key_bundle()`.

  12. melvo

    qy: You upload multiple pre keys. A device building a session with your device takes one of them and calls `session_pre_key_bundle()`. That pre key is passed to `session_pre_key_bundle()`.

  13. melvo

    moparisthebestโ€Ž: UWPX already implemented the latest version and we are working on an implementation for QXmpp / Kaidan.

  14. melvo

    You have to remove that pre key from your published bundle and publish a new one in order to you ensure that other devices do not take an already used pre key.

  15. qy

    I follow :) are sessions created reciprocally? i.e. Must i create one in response to someone creating one with me, or is one direction enough?

  16. melvo

    libomemo-c stores pre keys with `store_pre_key()` of the struct `signal_protocol_pre_key_store`.

  17. qy

    I think i was mainly thrown because libsignal makes no reference to randomly choosing from a prekey list

  18. qy

    > melvo wrote: > libomemo-c stores pre keys with `store_pre_key()` of the struct `signal_protocol_pre_key_store`. For local prekeys, right?

  19. qy

    `store_pre_key(uint32_t pre_key_id, uint8_t *record, size_t record_len, void *user_data)` has no discriminator for foreign keys

  20. qy

    I've implemented all the stores

  21. melvo

    Signal has a better approach for distributing pre keys. A device request one pre key, the server returns only one and removes it automatically. In OMEMO, we use PubSub and it has no such logic. So, we have to retrieve all pre keys and take care of them by ourselves.

  22. melvo

    Signal has a better approach for distributing pre keys. A device requests one pre key, the server returns only one and removes it automatically. In OMEMO, we use PubSub and it has no such logic. So, we have to retrieve all pre keys and take care of them by ourselves.

  23. melvo

    >For local prekeys, right? Yes.

  24. qy

    Ahh.

  25. melvo

    > `store_pre_key(uint32_t pre_key_id, uint8_t *record, size_t record_len, void *user_data)` has no discriminator for foreign keys You only have to store your own pre keys.

  26. qy

    Right, i think im clear on this now

  27. melvo

    ๐Ÿ™‚

  28. qy

    Hmm, just realised the biggest issue is that i need to close the loop and fully implement callbacks

  29. qy

    Since it uses pubsub rather than persistence

  30. melvo

    qy: What client is it?

  31. qy

    melvo: https://github.com/bqv/weechat-xmpp

  32. qy

    Another question, also

  33. qy

    Since clients have multiple devices, does that imply a session should be created for each device? Or one with every device as a recipient?

  34. qy

    I don't quite follow that workflow yet

  35. melvo

    Your client builds a session for each device (in practice, a client instance) in your contact's device list and for each device in your own device list but not to your own device.

  36. melvo

    Unfortunately, the term *device* is not precise because multiple client instances may run on one physical device. But in the world of Signal there is only one client instance per device...

  37. qy

    Yeah that makes sense, a device is a client. So is the group_session code used to make things work for all present clients?

  38. qy

    Or, is every stanza sent done n times for each client?

  39. qy

    I feel like if it was the latter i'd have noticed

  40. qy

    Yes, all in one, per the spec. I thought libsignal had something for multiple recipients but maybe i need to do that manually?

  41. vanitasvitae

    qy: just add all recipient devices to the message header

  42. vanitasvitae

    The message itself is only encrypted once.

  43. vanitasvitae

    And only one stanza is being sent

  44. vanitasvitae

    But each recipient can encrypt it (hopefully)

  45. melvo

    > Yeah that makes sense, a device is a client. And each client instance could even use multiple sessions for communicating with same end. Thus, I prefer the term endpoint. Enough meta discussion ๐Ÿ˜

  46. melvo

    > Yeah that makes sense, a device is a client. And each client instance could even use multiple sessions for communicating with same end. Thus, I prefer the term *endpoint*. Enough meta discussion ๐Ÿ˜

  47. qy

    Right, so the message is the payload, and each device gets a the key encrypted to their prekey in the header. But how does that translate to libsignal calls, if you excuse my ignorance ๐Ÿ˜… `session_cipher_encrypt(cipher, message, message_len, &encrypted_message)` drops out the payload, so where do the keys come from?

  48. qy

    Right, so the message is the payload, and each endpoint gets a the key encrypted to their prekey in the header. But how does that translate to libsignal calls, if you excuse my ignorance ๐Ÿ˜… `session_cipher_encrypt(cipher, message, message_len, &encrypted_message)` drops out the payload, so where do the keys come from?

  49. qy

    melvo: noted :p

  50. melvo

    The key material is retrieved by the store functions / PreKeyMessage.

  51. qy

    Im trying to interpret this from the dino code but it's nontrivial

  52. qy

    So libsignal's session_cipher creates the ciphertextmessage object, which is the message encrypted for that specific session/pair of endpoints

  53. qy

    Surely if that's done for every endpoint, the payloads will all be different?

  54. qy

    Modelling this on the libsignal readme code: ``` /* Create the session cipher and encrypt the message */ session_cipher *cipher; session_cipher_create(&cipher, store_context, &address, global_context); session_builder_set_version(cipher, 4); ciphertext_message *encrypted_message; session_cipher_encrypt(cipher, message, message_len, &encrypted_message); /* Get the serialized content and deliver it */ signal_buffer *serialized = ciphertext_message_get_serialized(encrypted_message); deliver(signal_buffer_data(serialized), signal_buffer_len(serialized)); ```

  55. qy

    Modelling this on the libsignal readme code: ``` /* Create the session cipher and encrypt the message */ session_cipher *cipher; session_cipher_create(&cipher, store_context, &address, global_context); ciphertext_message *encrypted_message; session_cipher_encrypt(cipher, message, message_len, &encrypted_message); /* Get the serialized content and deliver it */ signal_buffer *serialized = ciphertext_message_get_serialized(encrypted_message); deliver(signal_buffer_data(serialized), signal_buffer_len(serialized)); ```

  56. qy

    To [encrypt the message] as vanitasvitae was saying above, i'd need to do it with no recipient and then fetch the symmetric key used for the returned ciphertext, or something? Then encrypt _that_ for each endpoint, into the header

  57. qy

    > melvo wrote: > The key material is retrieved by the store functions / PreKeyMessage. Dino seems to create prekeymessage from the ciphertext_message in a test at least, am i missing a trick?

  58. qy

    I really wish i understood this thoroughly, i feel like im reinventing things i dont need to

  59. vanitasvitae

    I'm not familiar with C code, so I can't help with the details

  60. vanitasvitae

    But the flow is: fetch the device list(s), check if you have a session with each device, if not then fetch missing bundles and select a random prekey to build missing sessions (session_builder_process_prekey_bundle), then encrypt the message using a message key and encrypt the message key for each recipient

  61. qy

    Right, i think from that and scanning github for a while, i might be able to implement it

  62. qy

    vanitasvitae: Thanks :D

  63. vanitasvitae

    In libsignal-protocol-c, afaict what's called message is actually an AES message key

  64. vanitasvitae

    But I might be wrong

  65. qy

    Yeah, that confused me

  66. vanitasvitae

    So ciphertext_message is an encrypted message key

  67. qy

    Yeah, i think im clear on it all now :D thanks for bearing with me

  68. vanitasvitae

    you're welcome ๐Ÿ™‚