4.2 KiB
New acpeerstates table
A proposal to replace acpeerstates table,
which has columns
idaddrprefer_encryptedlast_seenlast_seen_autocryptpublic_keypublic_key_fingrprintgossip_timestampgossip_keygossip_key_fingerprintverified_keyverified_key_fingerprintverifiersecondary_verified_keysecondary_verified_key_fingerprintsecondary_verifierwith a newpublic_keystable with columnsidaddr- address of the contact which is supposed to have the private keypublic_key- a blob with the OpenPGP public keypublic_key_fingerprint- public key fingerprintintroduced_by- address of the contact if received directly inAutocryptheader, address ofAutocrypt-Gossipsender otherwiseis_verified- boolean flag indicating if the key was received in a verified group or nottimestamp- 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.
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.