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?
Chuckhas left
moparisthebest
Which version of 384 are you looking at? The current one no one implements or the previous one that everyone implements?
qy
Both, tbh
qy
Afaict so far the main difference is the namespaces
qy
Ive mainly focused on the axolotl version, since it's more accurate
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
qy
Or does libsignal not store bundles themselves?
qy
Perhaps they remain ephemeral, requested on need, and only sessions are stored?
qy
My understanding was that bundles were stored too
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()`.✎
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()`. ✏
melvo
moparisthebestโ: UWPX already implemented the latest version and we are working on an implementation for QXmpp / Kaidan.
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.
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?
melvo
libomemo-c stores pre keys with `store_pre_key()` of the struct `signal_protocol_pre_key_store`.
qy
I think i was mainly thrown because libsignal makes no reference to randomly choosing from a prekey list
qy
> melvo wrote:
> libomemo-c stores pre keys with `store_pre_key()` of the struct `signal_protocol_pre_key_store`.
For local prekeys, right?
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
qy
I've implemented all the stores
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.✎
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. ✏
melvo
>For local prekeys, right?
Yes.
qy
Ahh.
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.
qy
Right, i think im clear on this now
tritiumhas left
tritiumhas joined
Jeroenhas joined
Jeroenhas left
Jeroenhas joined
melvo
๐
Jeroenhas left
*IM*has joined
hellohas joined
hellohas left
Jeroenhas joined
Jeroenhas left
Jeroenhas joined
Jeroenhas left
Jeroenhas joined
Jeroenhas left
Jeroenhas joined
Jeroenhas left
Thilo Molitorhas left
Jeroenhas joined
Jeroenhas left
qy
Hmm, just realised the biggest issue is that i need to close the loop and fully implement callbacks
qy
Since it uses pubsub rather than persistence
tritiumhas left
Thilo Molitorhas joined
Jeroenhas joined
Jeroenhas left
sequalshas left
sequalshas joined
hellohas joined
Jeroenhas joined
Jeroenhas left
msavoritiashas left
Jeroenhas joined
melvo
qy: What client is it?
qy
melvo: https://github.com/bqv/weechat-xmpp
qy
Another question, also
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?
qy
I don't quite follow that workflow yet
meeson_has left
hellohas left
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.
hellohas joined
Jeroenhas left
Jeroenhas joined
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...
Jeroenhas left
Jeroenhas joined
melvohas left
melvohas joined
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?
qy
Or, is every stanza sent done n times for each client?
qy
I feel like if it was the latter i'd have noticed
sequalshas left
Jeroenhas left
meeson_has joined
qy
Yes, all in one, per the spec. I thought libsignal had something for multiple recipients but maybe i need to do that manually?
Jeroenhas joined
vanitasvitae
qy: just add all recipient devices to the message header
vanitasvitae
The message itself is only encrypted once.
vanitasvitae
And only one stanza is being sent
vanitasvitae
But each recipient can encrypt it (hopefully)
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 ๐✎
atomicwatchhas left
atomicwatchhas joined
meeson_has left
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 ๐ ✏
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?✎
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? ✏
qy
melvo: noted :p
melvo
The key material is retrieved by the store functions / PreKeyMessage.
Jeroenhas left
meeson_has joined
Jeroenhas joined
Jeroenhas left
Titihas joined
qy
Im trying to interpret this from the dino code but it's nontrivial
qy
So libsignal's session_cipher creates the ciphertextmessage object, which is the message encrypted for that specific session/pair of endpoints
qy
Surely if that's done for every endpoint, the payloads will all be different?
meeson_has left
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));
```✎
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));
``` ✏
meeson_has joined
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
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?
Jeroenhas joined
meeson_has left
Jeroenhas left
meeson_has joined
qy
I really wish i understood this thoroughly, i feel like im reinventing things i dont need to
Sevehas left
Jeroenhas joined
vanitasvitae
I'm not familiar with C code, so I can't help with the details
Jeroenhas left
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
Jeroenhas joined
Jeroenhas left
qy
Right, i think from that and scanning github for a while, i might be able to implement it
qy
vanitasvitae: Thanks :D
vanitasvitae
In libsignal-protocol-c, afaict what's called message is actually an AES message key
vanitasvitae
But I might be wrong
qy
Yeah, that confused me
vanitasvitae
So ciphertext_message is an encrypted message key
hellohas left
qy
Yeah, i think im clear on it all now :D thanks for bearing with me