-
Notifications
You must be signed in to change notification settings - Fork 5
Linked accounts (proposal #1)
To minimize the friction when creating organization accounts, we can enforce that the organization accounts are actually linked accounts to a personal one. This way, it will be easier to set them up, and the organization will have the ability to remove the access to it or move it at any time. They will also allow linking personal accounts if you don't use an old account anymore or because you want to.
A linked account will be basically an account that is associated with another account. When we link john@acme!
to john!
all messages sent to john@acme!
will actually be sent to john!
. Also, john!
could send messages as if they were coming from john@acme!
. Basically, a new redirect
field will be added to the resolver.
But not only organizations can link accounts, but also regular users could link their accounts.
From a user perspective, a way to link personal accounts could be this:
john@dev$ ./bm-client account link --account src! --to dst!
john@dev$ ./bm-client account unlink --account src!
You need to have access to the private key of src!
.. but you don't need access to the private key of dst!
. This means you can link to EVERY address possible if you like.
or this one, for organizations
john@dev$ ./bm-client organisation account create -a john@acme! -t john!
john@dev$ ./bm-client organisation account link -a john@acme! -t jane!
john@dev$ ./bm-client organisation account delete -a john@acme!
Please note that organization accounts will always be linked accounts, so routing_id
will be empty.
When you link an account you basically set a new redirect
field to the resolver pointing to the recipient hash.
john@dev$ ./bm-client message compose -f someone! -t john@acme! -s "Testing linked accounts" -b "default,Hello!"
- When someone sends a message to
john@acme!
their client will query for that address on the resolver. - The new
redirect
field will be pointing to the hash ofjohn!
. - Your client will query the new hash
- It will use the
public_key
to encrypt the message and send it
This way the message is E2EE using the key of the actual recipient. The message will appear as destined to john@acme!
instead of john!
so your client can sort the messages appropriately.
john@dev$ ./bm-client message compose -f john! --as john@acme! -t someone! -s "Replying to someone" -b "default,Hi there!"
If john!
wants to send a message as john@acme!
then the client needs to set appropriate headers so the message will appear as coming from john@acme!
.
- The client will use the private key of
john!
to encrypt the message - It will check that the
--as
parameter is given so it will query the resolver for that address If the address is linked tojohn!
, it will set the header as fromjohn@acme!
Should we set a newSignedByType
? - When
someone!
receives the message, it will see that it's coming from a linked account so it will use the linked account public key to decrypt it
- no complex organization stuff anymore on servers (invite tokens, whitelists of organizations, etc)
- no key checks for organizations when trying to delete keys
- a good cleanup of the key resolver with the organizational parts (I'm not sure if we need to send both parts anymore)
- we can easily remove a user from an organization
-
extra complexity in setting up the symlinking (we need to have extra fields like
redirect = <sha>
and do an extra lookup in the key resolver.. but that transparent for the user -
what about symlink to symlink?
Solved: This should not be a problem, but we need to consider the following few issues below:
-
what about the symlink loop (a to b to c to a)
Solved: This should be detected when creating a symlink by the resolver. If a loop is found, the symlink may not be created.
-
We should follow redirects up to a maximum of nested redirects (5?) and check if there is a loop
Solved: This should be done transparently on the key-resolver as well. It will redirect up to a certain level.
-
what happens when the organization links the account to other users? old messages sent by the original user won't be able to be decrypted by the recipients since they can't access the old public key
Solved: Old keys must be available to verify the
client signature
that is sent with a message. To authenticate a message, these old public key must be available. To do this, we can add the public key of the sender to the message catalog (we already do this). This, however, does not help authentication, because we still do not know for sure if the key is from the actual user that has sent the email (anyone could generate a keypair and send the message through their own server system). To verify authenticity, the recipient can check with the key resolver if the message's key belongs to the user (see below).
The key resolver does not store old keys but only the current key used for receiving mail. To check authenticity, the key resolver is used as OOB information for checking the client signature in messages. When a user rotates their key, the old key is not found anymore on the key resolver, making verification of the client signature impossible.
We solve this by sending the public key with the message. This already happens. To authenticate that it really is the sending user that has this key, we can ask the key resolver if the key is known for that user:
https://resolver.bitmaelum.com/account/<address>/<sha256 fingerprint>
This will return either a exist (204) or not found (404) response. This way, we can detect if a user has held a given public key, but we cannot query any keys as they are not available (anymore) on the resolver.
Any key rotation on the key resolver will add the hash-fingerprint tuple to the key history.
We store the history of old keys onto the key-resolver. So when you query a fingerprint on the resolver for a certain account, it can tell you if that was actually a key in the past.
This way, we can make sure that messages can be read even when the key is not valid anymore (because the symlink has changed, or the key has just rotated or any other situation).
We send the fingerprint of the CURRENT key inside a message. This is the key we need to check authenticity against.