Spellcheck

emdee 2022-10-09 14:29:01 +00:00
parent d7b42798cf
commit a60b299722
5 changed files with 144 additions and 123 deletions

@ -2,39 +2,62 @@ Previous: [[Home]]
## We need to solve the usage of Tox with multiple devices.
This 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 competion software deals with it.
This 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 friendly gammar and pronouns are used. _
**Woke Warning:** gender specific, non-android/furry friendly grammar and pronouns are 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. 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 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
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 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 annoucement and others getting it and being able to find him.
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 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.
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 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.
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 from a ToxID by a simple method: the default table contains a PersonaID that is the ToxPk (identity table).
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).
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.
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.
More concretely, the PersonaID mapping table would be like a dictionary with 2 (or more) types of entries; before the arrival of a blob, the table is by default (assuming json)
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,
the table is by default (assuming JSON)
```
{"Pk1": "Pk1",
"Pk2": "Pk2",
...}
```
So we could get the whole network switched over to accomodating 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:
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:
```
{"Pk1": "Pe1",
"Pe1": ["Pe1k1", "Pe1k2", ...],
"Pk2": "Pk2",
...}
```
or better stil, associated ordered dictionary mapping to a dictionary with nicknames
or better still, associated ordered dictionary mapping to a dictionary with nicknames
```
{"Pk1": "Pe1",
"Pe1": {"Device1Nick": "Pe1k1",
@ -42,40 +65,46 @@ or better stil, associated ordered dictionary mapping to a dictionary with nickn
"Pk2": "Pk2",
...}
```
where:
where:
* ```Pk1``` is the PK of user1,
* ```Pe1``` is the PersonaID of user1, which could be the public signing key of user1.
* ```["Pe1k1", "Pe1k2", ...]``` are the PKs of each of the devices of user1,
delivered in a blob signed by ```Pe1``
Richer formats for the table are obviously possible, but we want to maintain a structure that forsees this table being managed by a keyring manager like ```keepassxc```.
Richer formats for the table are obviously possible, but we want to
maintain a structure that foresees this table being managed by a
keyring manager like ```keepassxc```.
## MultiDevice Announcements Push
So if we modify the library and clients as described above how do we keep it up to date when a friend changes his devices?
If we know the PersonaID, how is the library code table of PersonaID to ToxPk mapping updated? We want this to be mainly automatic without bothering the user.
So if we modify the library and clients as described above how do we keep it up to date when a friend changes his devices? If we know the PersonaID, how is the library code table of PersonaID to ToxPk mapping updated? We want this to be mainly automatic without bothering the user.
We would need to modify the client code to save a copy if the mapping table,
so that when we start up a client, the mapping table is filled with last good values from the Persona storage. For the sake of this POC:
1. the storage file could be JSON, possibly encrypted with ToxESave, or
1. the storage file could be JSON, possibly encrypted with ToxESave, or
2. it could be a files in a Personae directory with files saved in JSON, like we do with avatars, with the filename being the PersonaID.json.
2. it could be a files in a Personae directory with files saved in JSON, like we do with avatars, with the filename being the ```PersonaID.json```.
Again, we want to maintain a structure that forsees this table being managed by a keyring manager like ```keepassxc```. It would not be saved in a profile, as this table spans multiple profiles.
Again, we want to maintain a structure that foresees this table being
managed by a keyring manager like ```keepassxc```. It would not be
saved in a profile, as this table spans multiple profiles.
Let's say we have a friend, and we know his ToxPk. We initially derive his PersonaID by setting it to the friend's public key - the entry in the table is a string.
We will call a blob the information that will update our PersonaID mapping to his active ToxID that is pushed to clients. We want to watch the the blob flow for changes; so what is the blob flow of information:
We will call a blob the information that will update our PersonaID
mapping to his active ToxID that is pushed to clients. We want to
watch the the blob flow for changes; so what is the blob flow of information:
1. If a blob is small we can base64 encode it and stick it in his status message,
2. We can do a blob push mechanism like we do for avatars, and push a blob into a file in a subdirectory called ```Personae```, with each blob stored in a filename with the PersonaID (signing public key) as the filename.json and handle updates the way we do avatars.
2. We can do a blob push mechanism like we do for avatars, and push a blob into a file in a sub-directory called ```Personae```, with each blob stored in a filename with the PersonaID (signing public key) as the filename.json and handle updates the way we do avatars.
3. We might push it as a DHT announcement.
Some clients may let the user decide whether of not to accept a blob update when it arrives.
Some clients may let the user decide whether of not to accept a blob
update when it arrives.
## MultiDevice Announcements Blob
@ -87,28 +116,63 @@ It has these characteristics:
2. It is small - 1K to 4K in size.
3) As we will need a NaCl signing keypair in order to sign out payload, the name, (PersonaID) can be the public key of the signing keypair - 32 bytes or 64 hex chars.
3) As we will need a NaCl signing keypair in order to sign the
payload, the name, (PersonaID) can be the public key of the signing keypair -
32 bytes or 64 hex chars.
4. If we push the blob info by DHT announcements,t it pushed regularly so people can get the PersonaID relatively soon - say hourly for now. Any longer means a person who has not connected to that friend before has to wait longer if they only have a PersonaID. If we push it like avatars, then it can be pushed once at start and subsequently on any changes.
4. If we push the blob info by DHT announcements, it pushed regularly
so people can get the PersonaID relatively soon - say hourly for now.
Any longer means a person who has not connected to that friend before
has to wait longer if they only have a PersonaID. If we push it like
avatars, then it can be pushed once at start and subsequently on any changes.
5) It might be encrypted so that the contents can not be seen in transit, but if the push mechanism is within Tox, it would be unnecessary.
5) It might be encrypted so that the contents can not be seen in transit,
but if the push mechanism is within Tox, it would be unnecessary.
6) It must be signed so that it can be verified to be from the PersonaID, so we will assume every person generates a NaCl signing 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.
6) It must be signed so that it can be verified to be from the
PersonaID, so we will assume every person generates a NaCl signing
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.
Each client would watch the stream or DHT announcements 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 the PersonaID to ToxPk mapping could be accessed even by people who were not yet your Friends - helping discovery. This may not be a good idea, depending on if it's encrypted. This set of ToxPks could be keys that open the encrypted blob. Anyone who already has a TokPk of the Persona could open the blob to get the update. Hence this encryption is different from most Tox encryption in that multiple keys can open it - like a multi-key Vera/True/dmwrapper container. But it might be enough for the blob to be signed, and that would be a good starting point - add encryption later if needed.
If we use DHT announcements, ach 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
the PersonaID to ToxPk mapping could be accessed even by people who
were not yet your Friends - helping discovery. This may not be a good
idea, depending on if it's encrypted. This set of ToxPks could be keys
that open the encrypted blob. Anyone who already has a ToxPk of the
Persona could open the blob to get the update. Hence this encryption
is different from most Tox encryption in that multiple keys can open
it - like a multi-key Vera/True/dmwrapper container. But it might be
enough for the blob to be signed, and that would be a good starting
point - add encryption later if needed.
The public signing key could be put into the status message field of each Person, and if each user put the same signature public key as the status message on each of his devices, then that signing PK can become 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.
The public signing key could be put into the status message field of
each Person, and if each user put the same signature public key as the
status message on each of his devices, then that signing PK can become
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.
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
2. It can be pushed as a status message. If we compress and base64 encode the blob, sign it and attach the signature in hex, and keep it under 1007 chars, then it can be set as your status message on all of your devices. The status message is visible to all of your friends so they all have a copy of the latest blob all of the time.
2. It can be pushed as a status message. If we compress and base64
encode the blob, sign it and attach the signature in hex, and keep it
under 1007 chars, then it can be set as your status message on all of
your devices. The status message is visible to all of your friends so
they all have a copy of the latest blob all of the time.
In fact we could do #2 first to get things going, and then do #1, which is more changes to the code, although a lot of the code could be morphed from the avatar code. Or you could push a blob as a file, if it got too big for a status message.
The same blob would be on each of your devices.
In fact we could do #2 first to get things going, and then do #1,
which is more changes to the code, although a lot of the code could be
morphed from the avatar code. Or you could push a blob as a file if
it got too big for a status message.
The same blob would be on each of a Person's devices.
### put that in the status message if less than 1007 bytes
@ -117,23 +181,35 @@ With the signature and the public key, this should leave room for at least 12 de
1007-128-64-2/(32+6+12) = 16
```
One problem with this is that only your Friends could verify the blob, which means
users you have never invited will not be able to verify, unless they had the signing public key independently (perhaps using /sendfile). But perhaps that's good.
One problem with this is that only your Friends could verify the blob,
which means users you have never invited will not be able to verify,
unless they had the signing public key independently (perhaps using
/sendfile). But perhaps that's good. Clients could watch status
message changes easily using the status_message callback.
If we pushed to the status message, clients could watch status message changes easily using the status_message callback.
### It can be pushed as files like avatars amongst Friends
### It can be pushed as files like avatars amongst Friend
All the avatar code could be repurposed to also handle blobs, with the signing public key put into the Person's status message.
All the avatar code could be repurposed to also handle blobs, with the
signing public key put into the Person's status message.
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.
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.
(The blob might be a signed way of associating nicknames with Pks if we use associated ordered dictionary mapping to a dictionary with nicknames.)
(The blob might be a signed way of associating nicknames with Pks if
we use associated ordered dictionary mapping to a dictionary with nicknames.)
The clients would manage this seemlessly to aggregate the ToxPks together under one Persona that is shown to the user. The library does 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 would manage this seamlessly to aggregate the ToxPks
together under one Persona that is shown to the user. The library does
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 clients let a user push a blob whenever he wants - like when he changes devices.
## MultiDevice Profiles
@ -142,29 +218,39 @@ existing profile. If you just copy a profile from one device to the next it will
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 <https://git.plastiras.org/emdee/tox_profile>
## MultiDevice Groups
Previously, we described how we simply copy a profile to a new devices and change the public/private keys as a starting point.
Previously, we described how we simply copy a profile to a new devices
and change the public/private keys as a starting point.
But we are left with as special problem with NGC groups.
The code is assumed to have been modified to handle Personas and, at first glance, NGC groups become groups of Personas. Each member of the group is a Persona, and uses the table lookup to get the active ToxPk.
The code is assumed to have been modified to handle Personas and, at
first glance, NGC groups become groups of Personas. Each member of the
group is a Persona, and uses the table lookup to get the active ToxPk.
But the group structure in the profile has a copy of the founder's shared_state.founder_public_key (group_pack.c#L293) So if the profile being copied onto a new device is the profile of the founder, then this key would need to be updated too.
But the group structure in the profile has a copy of the founder's
shared_state.founder_public_key (group_pack.c#L293) So if the profile
being copied onto a new device is the profile of the founder, then
this key would need to be updated too.
Besides the group keypair in #L351-2
* bin_pack_bin(bp, chat->chat_public_key, EXT_PUBLIC_KEY_SIZE); // 1
* bin_pack_bin(bp, chat->chat_secret_key, EXT_SECRET_KEY_SIZE); // 2
* bin_pack_bin(bp, chat->chat_public_key, EXT_PUBLIC_KEY_SIZE); // 1
* bin_pack_bin(bp, chat->chat_secret_key, EXT_SECRET_KEY_SIZE); // 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 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? These keys have to be updated with the new keypair of the new profile.
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.
There is Python script to parse profiles that could be modified to rekey them at:
There is Python script to parse profiles that could be modified to rekey at:
https://git.plastiras.org/emdee/tox_profile

@ -1,26 +0,0 @@
Previous: [[MultiDeviceAnnouncementsPush]]
So what is the blob of information that is pushed by DHT annoucements/
It has these characteristics:
1) It has 2 things - a name and a payload.
2) It is small - 1K to 4K in size.
3) The name is related to, and derivable from, the PersonaID - say the name is the PersonaID for now.
4) It it pushed regularly so people can get the PersonaID relatively soon - say hourly for now. Any longer means a person who has not connected to that friend before has to wait longer if they only have a PersonaID.
5) It is encrypted so that the contents can not be seen in transit.
6) It is encrypted so that it can be verified to be from the PersonaID.
So here is a best guess of how the encryption works. I'm not a crypto guy, so please take it with a grain of salt and help with suggestions.
The blob is intended to be the mapping to an active ToxID, and could be a mapping to a set of ToxIDs, the set of that Personas devices, with one marked active. This set of ToxIDs could be keys that open the encrypted blob. Anyone who already has a ToxID of the Persona could open the blob to get the update. So this encryption is different from most Tox encryption in that multiple keys can open it.
Unknown for now is does the client have to send an add request to the new ToxID to make it active if they have never seen it before? I assume yes.
Either way the clients would manage this seemlessly to aggregate the two ToxIDs together under one Persona that is shown to the user. The library does most of this by accepting the update from the blob to update the table pointing from PersonaID to the new ToxID.

@ -1,10 +0,0 @@
Previous: [[MultiDeviceAnnouncementsBlob]]
In order for MultiDevice to work, we need to bootstrap a new devices from an
existing profile. We assume all clients use a common tox profile format, though
most complement the Tox profile with an ini file or similar.
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 running the rekeyed profile could send a DHT announcement updating to the new ToxID. The old keys would be added to the new profile's friends list.
The profile rekey utility could also do other things at the same time, like empty the TCP_RELAYS section of the profile if desired.

@ -1,25 +0,0 @@
Previous: [[MultiDeviceInitialization]]
In the initialization process we described in [[MultiDeviceInitialization]] we simply copy a profile to a new devices and change the public/private keys as a starting point.
But we are left with as special problem with NGC groups.
The code is assumed to have been modified to handle Personas and, at first glance, NGC groups become groups of Personas. Each member of the group is a Persona, and uses the table lookup to get the active ToxID.
But the group structure in the profile has a copy of the founder's shared_state.founder_public_key (group_pack.c#L293) So if the profile being copied onto a new device is the profile of the founder, then this key would need to be updated too.
Besides the group keypair in #L351-2
* bin_pack_bin(bp, chat->chat_public_key, EXT_PUBLIC_KEY_SIZE); // 1
* bin_pack_bin(bp, chat->chat_secret_key, EXT_SECRET_KEY_SIZE); // 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:
* self_public_key #L353
* self_secret_key #L354
Are these simply the keypair of the Persona that is the new profile? If so, then these keys have to be updated with the new keypair of the new profile.
There is Pythonscript to parse profiles that could be modified to rekey them at:
https://git.plastiras.org/emdee/tox_profile

@ -1,4 +0,0 @@
# Anthony Bilinski