Introduction
Disambiguation
Terminology and roles
Objectives
The server
Creating a Port
Sharing a Port
Connecting over a Port
Alice verifying Bob
Bob verifying Alice
Replay resistence
Limitations
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:
Identifier protection: neither party (Alice nor Bob) know any persistent identifiers for each other
Man-in-the-middle attack resistance: both parties can be confident that they are connected to each other
A shared secret: a key over which secure communication can be established
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:
Authenticate a client’s identity
Route packets to a client
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.
Alice requests the server for a line link
The server creates a random, high entropy id, line_link, associates it to Alice and returns it to Alice
Alice performs keygen() to get private_key_alice and public_key_alice
Alice performs rand() to get RAD (random associated data)
Alice combines line_link, public_key_alice and RAD into a Port
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.
Bob submits line_link to the server
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
The server returns line_id to bob
The server sends a packet containing line_link and line_id to alice
Bob now knows that line_id is associated on the server to someone claiming to be Alice
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.
Bob performs keygen() to get private_key_bob and public_key_bob
Bob performs DH(private_key_bob, public_key_alice) to get secret
Bob performs encrypt(secret, RAD) to get encrypted_RAD
Bob sends Alice public_key_bob, encrypted_RAD
Upon receiving Bob’s message Alice performs DH(private_key_alice, public_key_bob) to get secret
Alice performs decrypt(secret, encrypted_RAD) to get potentially_RAD
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.