diff --git a/MultiDeviceAnnouncementsPOC.md b/MultiDeviceAnnouncementsPOC.md index 1e0f09b..b3db367 100644 --- a/MultiDeviceAnnouncementsPOC.md +++ b/MultiDeviceAnnouncementsPOC.md @@ -5,40 +5,42 @@ Previous: [[Home]] This proof-of-concept (POC) is based on the premise that solving the usage of Tox with multiple devices is an urgent problem, as anyone with mobiles runs into it, and all the competition software deals with it. - -**Woke Warning:** gender specific, non-android/furry friendly grammar is used throughout. +MultiDevice is much easier in centralized systems and our decentalization +is why it's hard for us; if we make it, we make be the first ever! + +**Woke Warning:** gender specific, non-android/furry friendly grammar +is used throughout. The idea here is to address one simple usecase: a person can have multiple devices and he wants one device to be "active" at any given time. -o he pushes so kind of announcement of what device he is currently +So he pushes so kind of announcement of what device he is currently using so that others can communicate to the device he is currently using. -The POC ignores for now the problem of history sync that this -creates. We can address that later perhaps with tools like rsync. - -The proposal assumes that there will be a lag time between him pushing -an announcement and others getting it and being able to find him. +The POC ignores the problem of history sync that this creates. +Others can address that later perhaps with tools like rsync. The idea is to firstly define a PersonaID, much like a ToxPk that stays permanent across his devices, and maps the Person to the active ToxPk. -So the first step is to change all library code and all clients to -work with PersonaIDs as well as ToxPks. The PersonaIDs would be client facing, -and the ToxPk code will be internal. A simple step of duplicating all -code calls that deals with ToxPks to have a 1:1 layer of calls on top -that take the PersonaID and consult a table that contains the active -ToxPk, and then calls the ToxPk function. +So the first step is to extend all library code and all clients to +work with PersonaIDs as well as ToxPks. The PersonaIDs would be client +facing, and the ToxPk code would be for internal access. A simple +implementation would be duplicating all code calls that deals with +ToxPks to have a layer of calls on top that take the PersonaID and +consult a table that contains the active ToxPk, and then calls the +ToxPk function. For the sake of argument, let's say that the table is initially -populated with all the existing known ToxPks by deriving a default -PersonaID ToxID by a simple method: the default table contains a PersonaID -that is the ToxPk (identity table). +populated with all the existing ToxPks by deriving a default PersonaID +ToxID by a simple method: the default table contains a PersonaID that +is the ToxPk (identity table). So we can add this layer of PersonaID->ToxPk mapping to the library -and all clients right away with no breakage. In time, the clients move -to showing the PersonaID not the ToxPk as the primary data, and add in -the clients the ability to see the table of Personae -> ToxPks (but -maybe not change the entries), and the active ToxPk for each PersonaID. +and all clients right away with no breakage. In time, the clients will +move to showing the PersonaID not the ToxPk as the primary client-facing ID, +and extend the clients with the ability to see the table of Personae -> +ToxPks (but maybe not change the entries), and the active ToxPk for +each PersonaID. More concretely, the PersonaID mapping table would be like a dictionary with 2 (or more) types of entries; before the arrival of a blob update, @@ -47,7 +49,7 @@ the table is by default (assuming JSON) {"Pk1": "Pk1", "Pk2": "Pk2", ...} - ``` +``` So we could get the whole network switched over to accommodating PersonaIDs with no breakage. After the arrival of a blob to update the table, the PersonaID is an ordered dictionary mapping to a list of device PKs: @@ -56,7 +58,7 @@ the PersonaID is an ordered dictionary mapping to a list of device PKs: "Pe1": ["Pe1k1", "Pe1k2", ...], "Pk2": "Pk2", ...} - ``` +``` or better still, associated ordered dictionary mapping to a dictionary with nicknames ``` {"Pk1": "Pe1", @@ -64,7 +66,7 @@ or better still, associated ordered dictionary mapping to a dictionary with nick "Device2Nick": "Pe1k2", ...}, "Pk2": "Pk2", ...} - ``` +``` where: * ```Pk1``` is the PK of user1, @@ -135,7 +137,7 @@ keypair and uses the same keypair for all of his devices. The public key of the signing keypair can be used as the PersonaID. If a secret is used as the seed of the signing keypair, then the generated keypair is reproducible. -If we use DHT announcements, ach client would watch the stream for +If we use DHT announcements, each client would watch the stream for blobs named the PersonaID that they are interested in, which they know from the public signing key being in the status message of the friends. Pushing the blob through DHT announcements would mean that @@ -156,8 +158,11 @@ the PersonaID. The mapping table can be automatically scanned and any entries for which the PersonaID == ToxPk could be automatically updated to use the signing key as the PersonaId. -So let's say for now to focus this discussion, we will ignore DHT -announcements. + +I had assumed we would have to use the DHT to deal with decentralization. +But this POC makes me think we can use the toxcore status_message +and avatar_files code to do it without the DHT. So let's say for now +to focus this discussion, we will ignore DHT announcements. 1. Set your status message to be the signing public key and push the blob by some means like avatars to Friends, or @@ -190,15 +195,19 @@ message changes easily using the status_message callback. ### It can be pushed as files like avatars amongst Friends All the avatar code could be repurposed to also handle blobs, with the -signing public key put into the Person's status message. +signing public key put into the Person's status message. Avatars are +simple file transfers; there is a WHOLE byte dedicated for "file_kind", +which means we can "just" add a new file_kind and use the exising file +transfer code. In the beginning the clients would not need to be able +to generate the blob - a simple Python script could do it outside the clients. - -Unknown for now is does the client have to send an add request to any -new ToxPks found in the blob (new devices) to make them active if they -have never seen the PK before? I assume yes. If so then it complicates -things a little as the blob might need to contain ToxIDs. The code -could accept either, distinguishing by length. Or you could require that -the Person already be a Friend with that device. +Unknown for now is does the client have to send a Friend ```add +request``` to any new ToxPks found in the blob (new devices) to make +them active if the client has never seen the PK before? I assume yes. +If so then it complicates things a little as the blob might need to contain +ToxIDs. The code could accept either ToxPks or ToxIds, distinguishing +by length. Or you could just require that the Person already be a +Friend with that device before the information in the table was useable. (The blob might be a signed way of associating nicknames with Pks if we use associated ordered dictionary mapping to a dictionary with nicknames.) @@ -209,14 +218,17 @@ most of this by accepting the update from the blob to update the table pointing from PersonaID to the new list of ToxPks (devices) with the first one being the active one. -The clients let a user push a blob whenever he wants - like when he changes devices. +The generation and signing verification of the blobs could be done +outside of the clients in a utilty common to all clients. The clients +let a user push a blob whenever he wants - like when he changes devices. ## MultiDevice Profiles In order for MultiDevice to work, we need to bootstrap a new devices from an existing profile. If you just copy a profile from one device to the next it will not work as you cannot have 2 profiles with the same keys online at the same time. We could have a simple utility that rekeys a profile and creates a new ToxID, so that we could copy a profile and rekey it. Then the new client would push a new blob with the new device's PK, signed by the signing keypair which is independent of profiles. -The profile rekey utility could also do other things at the same time, like edit the TCP_RELAYS section of the profile if desired. See +The profile rekey utility could also do other things at the same time, like edit the TCP_RELAYS section of the profile if desired. +See ## MultiDevice Groups @@ -241,16 +253,38 @@ Besides the group keypair in #L351-2 The chat->chat_secret_key is all zeros, I assume in everyone but the founder's profile. -It seems also that self's keypair are saved to the group: +It seems also that self's group keypair are saved to the group: * self_public_key #L353 * self_secret_key #L354 -These are not simply the keypair of the Persona that is the new profile - -how are they created? Do these keys have to be updated with the new keypair -of the new profile? Or do you only copy the profile that was in use when -you first joined the group as a user. Wrinkle. +Do these keys have to be updated with the new keypair of the new +profile? Or do you only copy the keys from the profile that was in +use when the Person first joined the group as a user - wrinkle. In +which case, the notion of the blob needs extending from just the +ToxPks and nicknames of each of the devices, to include the secret +keys of that Persona for each NGC group the Persona belongs to. + +(Aside: I don't like the idea of keeping secret keys in profiles; they +should be managed by a keymanager. In a corporate setting, this will +be a requirement.) There is Python script to parse profiles that could be modified to rekey at: https://git.plastiras.org/emdee/tox_profile +## Summary + +The changes to the core are not large: +1. Change the status message callback to look for public signing keys +2. Extend the avatar file transfer mechanism to transfer blobs +3. Use the public signing keys to verify the blobs +4. Use the blobs to populate the table, and designate one entry as active. +5. Wrap all the calls that use a PK to look in the table for the active PK. + +All existing unmodified users would continue to work: no testnet required. + +Assuming the blobs were created by an independent stand alone utility, +the changes to the clients are not large: +1. Consult the mapping table and show it to the users. +2. Accept or reject new blob updates. +3. Redefine the notion of contacts to point to the PersonaID