Skip to content

Securejoin v3: 4-step protocol with symmetric encryption #7396

@Hocuri

Description

@Hocuri

We would like to change the securejoin protocol. Most importantly, all securejoin messages will be encrypted.

Securejoin is the protocol than runs when the user scans a QR code or clicks on an invite link. By convention, the person who creates the QR codes is called "Alice", and the person who scans it is called "Bob".

Motivation

  • Today, the first message sent in the Securejoin protocol is sent unencrypted. This leaks the joiner's cryptographic identity to the server operator. Also, it needs special handling in chatmail servers, which otherwise only allow encrypted messages. It also makes workarounds like Detect Secure-Join request step using only Secure-Join-Invitenumber #7687 necessary.
  • Today, there are two tokens in the QR code, AUTH and INVITENUMBER. Once everyone upgrades, we can get rid of the INVITENUMBER, making QR codes a little bit smaller.

Protocol flow chart

Legacy Securejoin Securejoin v3
Image Image

If Bob already knows Alice's pubkey, there is a shortcut: The first two messages can be skipped.

Click to see a comparison with alternative protocols

image

Rationale and requirements

Click to see rationale and required security properties

Rationale

  • Since we can't do anything asymmetric in the first message from Bob to Alice, it has to be encrypted symmetrically.
    • Since this means that a server operator who has the AUTH token (by scraping the web for public QR codes) can decrypt this message, this message can't contain Bob's display name or avatar. We also don't want to leak Bob's cryptographic identity, so we also don't include Bob's public key (an alternative here would be to create a new keypair Bob-temp, which is what the 3-step protocol does, but this just adds unnecessary complexity).
  • Since we want to give Alice the opportunity to review join requests (as a future improvement that doesn't require breaking the protocol), Alice can't send any private data in the second message.
    • So, she only sends her pubkey in the second message. Since Alice's fingerprint is in the QR code, a server operator who scraped her QR code from the web will also know the pubkey; this means that we can safely send the pubkey without potentially leaking any private data.
    • If we want to protect Alice's cryptographic identity from someone who sees her QR code, then this can be a future improvement (Alice can just create a new keypair Alice-temp for this) but is out of scope for now.
  • In the third message, Bob can send his pubkey, avatar and displayname.
  • In the fourth message, Alice can send her avatar, displayname, and broadcast invitation.

About the complexity "Alice needs to create a Bob-contact without knowing his fingerprint": It should be possible for Alice to receive and answer the first message without any database changes. This will probably mean that create_send_msg_jobs() and MimeFactory::from_msg() is not used, with some parts which are needed extracted into a separate function. I still have to check whether it makes sense to use MimeFactory::render().

Required security properties

Security properties we want:

  • No MitM possible (assuming the server operator can't modify the QR code)
  • No metadata sent in cleartext

Security properties we probably want:

  • Even if the server operator sees the QR code, they can't find profile data
  • Even if the server operator sees the QR code, they can't find Bob's key-fingerprint
  • Possible to switch to quantumn-resistant cryptography (which means that we can't just put the pubkey or the first part of a DH exchange into the QR code, bc quantumn-resistant cyphers are long)

Other possibly-interesting security properties:

  • Quantumn-resistant, assuming the channel operator can't see the QR code (we can simply encrypt everything sensitive with the AUTH token for this)
  • We can let Alice review Bob's request before answering to the silent SMS (this requires profile data in the first message, though, so it's probably incompatible with other security goals)

Security properties we don't need to talk about right now:

  • Even if the server operator sees the QR code, they can't see Alice's key-fingerprint (this will require an Alice-temp fingerprint, which is independent of which protocol we choose)

Implementation considerations

  • There is this small bug that is not fixed by Securejoin v3:
      // TODO: There is a known bug in `observe_securejoin_on_other_device()`:
      // When Bob joins a group or broadcast with his first device,
      // then a chat with Alice will pop up on his second device.
    
  • When Alice answers the first message, she doesn't know anything about Bob, not even his pubkey. So, she can't create a contact for him; but we can create and send the answer message pretty much directly, without using all of the existing sending logic that expects a contact id.
  • The 3rd and 4th message is exactly the same as in legacy securejoin, and uses the same code paths.
  • Therefore, it's easier to call the 3rd message vc-request-with-auth for backwards compatibility, even though this doesn't exactly describe what it does

Backwards compatibility

  • In order to stay backwards compatible, QR codes will get a new parameter &v=3. This means that old clients will continue to understand them. Unfortunately, it also means that we need to include an INVITENUMBER, even though it's only needed if an old client scans the QR code.
  • For the case that Alice or Bob has two devices, one of which understands the new protocol, and one of which doesn't:
    • What's easy to solve is the case that the old device created or scanned the QR code; in this case, we just need to make sure that we continue to understand these messages in observe_securejoin_on_other_device().
    • If the new device created or scanned the QR code:
      • The old device won't be able to decrypt the first two messages, because they are symmetrically encrypted.
      • Therefore, we need to make sure not to self-send the first two messages.
      • Apart from that, observe_securejoin_on_other_device() should understand the request-with-auth or member-added/contact-confirm message just fine.

For reference, this is a follow-up to that comment: #7042 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions