mirror of
https://github.com/chatmail/core.git
synced 2026-04-27 02:16:29 +03:00
132 lines
4.3 KiB
Markdown
132 lines
4.3 KiB
Markdown
# New acpeerstates table
|
|
|
|
A proposal to replace `acpeerstates` table,
|
|
which has columns
|
|
- `id`
|
|
- `addr`
|
|
- `prefer_encrypted`
|
|
- `last_seen`
|
|
- `last_seen_autocrypt`
|
|
- `public_key`
|
|
- `public_key_fingrprint`
|
|
- `gossip_timestamp`
|
|
- `gossip_key`
|
|
- `gossip_key_fingerprint`
|
|
- `verified_key`
|
|
- `verified_key_fingerprint`
|
|
- `verifier`
|
|
- `secondary_verified_key`
|
|
- `secondary_verified_key_fingerprint`
|
|
- `secondary_verifier`
|
|
with a new `public_keys` table with columns
|
|
- `id`
|
|
- `addr` - address of the contact which is supposed to have the private key
|
|
- `public_key` - a blob with the OpenPGP public key
|
|
- `public_key_fingerprint` - public key fingerprint
|
|
- `introduced_by` - address of the contact if received directly in `Autocrypt` header, address of `Autocrypt-Gossip` sender otherwise
|
|
- `is_verified` - boolean flag indicating if the key was received in a verified group or not
|
|
- `timestamp` - timestamp of the most recent row update
|
|
|
|
The table has consraints `UNIQUE(addr, introduced_by)`.
|
|
Note that there may be multiple rows with the same fingerprint,
|
|
e.g. if multiple peers gossiped the same key for a contact they all are introducers of the key.
|
|
|
|
`prefer_encrypted` is moved to the `contacts` table.
|
|
|
|
Maybe fingerprint is the primary key, at least there should be an index.
|
|
|
|
|
|
## Using the table to select the keys
|
|
|
|
### Sending a message to 1:1 chat
|
|
|
|
When sending a message to the contact in a 1:1 chat,
|
|
encrypt to the key where `introduced_by` equals `addr`:
|
|
```
|
|
SELECT *
|
|
FROM public_keys
|
|
WHERE addr=? AND introduced_by=addr
|
|
```
|
|
This row is guaranteed to be unique if it exists.
|
|
|
|
If direct Autocrypt key does not exist,
|
|
use the most recent one according to the timestamp key gossiped for this contact:
|
|
```
|
|
SELECT *
|
|
FROM public_keys
|
|
WHERE addr=?
|
|
ORDER BY timestamp DESC LIMIT 1
|
|
```
|
|
|
|
If the table contains a row with selected key and `is_verified` flag set,
|
|
display a green checkmark and "Introduced by <introduced_by>" in the 1:1 chat/contact profile.
|
|
Note that row with verification may be older than the most recent gossip.
|
|
|
|
### Sending a message to unprotected group chat
|
|
|
|
When sending a message to the contact in a non-verified group chat,
|
|
encrypt to the same key as used in 1:1 chat
|
|
and (NEW!) one or more most recent gossiped keys introduced by chat members:
|
|
```
|
|
SELECT public_key
|
|
FROM public_keys
|
|
WHERE addr=? AND introduced_by IN (<chat-member-list>)
|
|
ORDER BY timestamp DESC
|
|
```
|
|
It does not matter if the gossiped key has `is_verified` flag.
|
|
|
|
### Sending a message to protected group chat
|
|
|
|
When sending a message in a protected group chat,
|
|
construct a list of candidate keys for each contact
|
|
the same way as in an unprotected chat,
|
|
but then filter out the keys which do not have `is_verified` flag.
|
|
|
|
|
|
## Updating the table
|
|
|
|
When executing "setup contact" protocol
|
|
with the contact,
|
|
set the row with `addr` and `introduced_by` being equal
|
|
to the contact address and `is_verified` is true.
|
|
In this case the contact becomes directly verified.
|
|
|
|
When receiving a message,
|
|
first process the `Autocrypt` key,
|
|
then check verification properties to detect if gossip is signed with a verified key,
|
|
then process `Autocrypt-Gossip` key.
|
|
|
|
### 1. Processing the Autocrypt header
|
|
|
|
Take the key from the Autocrypt header
|
|
and insert or update the row
|
|
identified by `addr` and `introduced_by` being equal to the `From:` address.
|
|
Notify about setup change and reset `is_verified` flag if the key fingerprint has changed.
|
|
Always update the timestamp.
|
|
|
|
Update `prefer_encrypted` in the contacts table as needed
|
|
based on the `Autocrypt` header parameters,
|
|
whether the message is signed etc.
|
|
|
|
### 2. Check verification
|
|
|
|
Determine whether the green checkmark should now be displayed
|
|
on the 1:1 chat and update it accordingly,
|
|
insert system messages,
|
|
get it into broken state or out of it.
|
|
|
|
Now we know if the message is signed with a verified key.
|
|
|
|
### 3. Process `Autocrypt-Gossip`
|
|
|
|
Insert or update gossip keys
|
|
```
|
|
INSERT INTO public_keys (addr, public_key, public_key_fingerprint, introduced_by, is_verified, timestamp)
|
|
VALUES (?, ?, ?, <introducer>, ?, <now>)
|
|
ON CONFLICT
|
|
DO UPDATE SET public_key=excluded.public_key, public_key_fingerprint=excluded.public_key_fingerprint
|
|
```
|
|
|
|
`is_verified` should be set if the message is signed with a verified key,
|
|
independently of whether the key was gossiped in a protected chat or not.
|