The Port Protocol, Version 1

The Port Protocol, Version 1

Introduction

This document outlines the basis of the first version of the Port Protocol which forms the basis of communication over “Port, by Numberless”, a messaging app that allows connections to form without users having to share any persistent unique identifiers (email addresses, phone numbers or usernames). 

The Port Protocol is used to form connections in Port using the flagship connection instrument, a Port. 

Disambiguation

The Port Protocol differs from the SuperPort Protocol and the ContactPort Protocol which can also be used within Port to form connections under different circumstances.

Terminology and roles

  • Alice is the name of the user/client who creates a Port

  • Bob is the name of a user/client who attempts to connect with Charlie over a Port

  • The Server represents the servers operated by Numberless. The capabilities, trust level and awareness of this server are discussed in section X below.

  • hash refers to the sha-256 cryptographic hashing algorithm

  • rand() -> str refers to the generation of a high-entropy random string using a cryptographically secure random number generator provided by the host operating system

  • X25519 refers to the diffie-hellman key exchange using Curve25519 (https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)

    • keygen() -> private_key, public_key refers to the generation of a keypair under the diffie-hellman key exchange, x25519

    • DH(private_key_1, public_key_2) -> shared_secret refers to the generation of a secret by “mixing” one’s private key with a counterparty’s public key

  • encrypt(key, plaintext) -> ciphertext refers to the encryption using AES256 in CBC mode.

  • decrypt(key, ciphertext) -> plaintext refers to the decryption of a ciphertext using AES256 in CBC mode

  • A line is a connection between two parties (think of “line of communication”)

  • A line link is a high entropy token that a server associates with a user to be used to form exactly one line at some point in the future

Objectives

While connecting two clients, the Port Protocol aims to provide the following:

  1. Identifier protection: neither party (Alice nor Bob) know any persistent identifiers for each other

  2. Man-in-the-middle attack resistance: both parties can be confident that they are connected to each other

  3. A shared secret: a key over which secure communication can be established

  4. Replay resilience: a way to ensure that a Port cannot be re-used to connect with the same party after it has already been used

The server

The Port server can:

  1. Authenticate a client’s identity

  2. Route packets to a client

  3. Cache packets intended for a client if they are offline


The Port servers cannot correlate one’s identity within Port to their identity in real-life or on other services.

The server is treated as a cooperative but un-trustworthy entity. A client expects the server to do as instructed, but the client also takes steps to ensure that a malicious server cannot garner information that they are not privy to and are able to detect and reject malicious responses.

Creating a Port

To initiate the Port Protocol, Alice must generate a Port. 


  1. Alice requests the server for a line link

  2. The server creates a random, high entropy id, line_link, associates it to Alice and returns it to Alice

  3. Alice performs keygen() to get private_key_alice and public_key_alice

  4. Alice performs rand() to get RAD (random associated data)

  5. Alice combines line_link, public_key_alice and RAD into a Port

  6. The Port can be encoded in any form, but is primarily seen as a QR code in Port

Sharing a Port

Alice now shares the Port with Bob over a secure channel. Most often this happens face to face using a Port QR code. Bob scans a QR code on Alice’s screen and information is securely shared across these devices.

Connecting over a Port

When Bob receives Alice’s Port, he can initiate a connection with the cooperation of the server.


  1. Bob submits line_link to the server

  2. The server maps line_link back to Alice and generates line_id (a line is a 1-1 connection) and associates it with both Alice and Bob

  3. The server returns line_id to bob

  4. The server sends a packet containing line_link and line_id to alice

  5. Bob now knows that line_id is associated on the server to someone claiming to be Alice

  6. Alice now knows that line_id is associated on the server to someone claiming to be Bob


The server and clients are now in a state where they can send messages intended for each other to the server by associating a packet with line_id.

Once the line between Alice and Bob is established, Bob must provide proof of identity to Alice.


  1. Bob performs keygen() to get private_key_bob and public_key_bob

  2. Bob performs DH(private_key_bob, public_key_alice) to get secret

  3. Bob performs encrypt(secret, RAD) to get encrypted_RAD

  4. Bob sends Alice public_key_bob, encrypted_RAD

  5. Upon receiving Bob’s message Alice performs DH(private_key_alice, public_key_bob) to get secret

  6. Alice performs decrypt(secret, encrypted_RAD) to get potentially_RAD

  7. If potentially_RAD == RAD, Alice can confirm that she is in fact connected to Bob, and secret is something that only Bob knows as long as Bob’s client has not been compromised. If they are not equal, the connection is rejected as invalid


At this point Alice is confident that secret is a shared secret between her and Bob.

This process is sped up in the actual app by piggybacking step 4 with step 4 of “Connecting over a Port”.

Bob verifying Alice

Bob’s verification that he is connected to Alice is based upon her ownership of “secret”.

Since Alice generated public_key_alice and shared it directly with Bob, assuming that her client is not compromised, she is the only person who owns private_key_alice.


Only someone possessing private_key_alice can generate secret by performing DH(private_key_alice, public_key_bob).

Bob can safely assume that any message encrypted using secret must have come from Alice.

At this point, “secret” can safely be considered a shared secret by both parties.

Replay resistance

The moment Alice receives the packet from the server indicating that line_link has been used to form a connection, the line_link is locally marked as invalid. This means that Alice will never accept multiple connections from the server that have used the same initial context.


Alice and Bob also use unique private and public keys and RADs for each Port creation and usage. This means that a Port can never be re-used even if the server cooperates with a malicious client by providing them with line links that are considered valid by a client.

Limitations

The Port Protocol cannot prevent a denial of service by the server if it refuses to cooperate by routing messages to the best of its ability.


The Port Protocol does not provide requirements for security augmentation on top of creating the shared secret. Similarly, it provides no restrictions on what can be implemented. Once the secure channel is established between both parties, they may proceed to set up stronger encryption standards as needed.


There is no clearly defined restriction on how Ports are shared. The security of the Port Protocol is predicated on the secondary channel that the Port is shared over being secure. If a Port is shared over an existing group chat, for example, the first user of the Port can form a connection with you, who may not be the intended recipient.