SSB Rooms 2.0

Revision: 2022-10-10

Author: Andre Medeiros contact@staltz.com

License: This work is licensed under a Creative Commons Attribution 4.0 International License.

Abstract

A room server is an SSB peer with privileged internet presence (for instance, not behind a NAT layer) which allows its clients to perform tunneled connections wich each other. For practical purposes, room clients seem to be connected to each other directly, but the room is an intermediary. Connections between server and client are end-to-end encrypted via secret-handshake, as well as in tunneled connections between room clients, so that the room server cannot eavesdrop on the payloads in the tunneled connections. This document describes new capabilities for rooms, such as user aliases, privacy modes, and tunneled authentication.

Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

Table of contents

Stakeholders

Persons or organizations that are involved or engaged in or around room servers. They may hold responsibilities or powers, and may cause harm to other stakeholders when their responsibilities or powers are abused. They hold interest in engaging with other stakeholders while managing the risk for harm associated with engagement. Harm mitigation such as Privacy modes is important when discussing stakeholders.

Room admin

Person or organization responsible for operating the room server, and has full access rights over the server's resources such as logs, disk, memory, etc. In other words, this person or organization physically owns the room server or has SSH access to the remote server hosted in some PaaS cloud provider.

Typically, the admin possesses an SSB ID (it's very common, but not necessarily always the case), and is also a moderator in the room.

Internal user

SSB user who accesses the room server and is considered internal because they have already joined the room and may even have registered an alias in the room.

Specification

Definition: an internal user of a room is any SSB ID for which the room grants a tunnel address. In other words, if an SSB ID is reachable via a tunneled connection through a room server, then they are considered an internal user of that room.

Becoming an internal user: read more about that in Joining a room.

External user

Any SSB user who is not an internal user of the room (i.e. do not have a usable tunnel address referencing the room), but may still interact with the room server in meaningful ways, for instance with tunneled connections, alias endpoints or alias consumption.

Moderator

A moderator is an internal user that has acquired special privileges in the web dashboard and actions allowed by the dashboard.

Moderators can use sign-in to access the dashboard.

Setup

There are different ways a room server can be configured.

Components

A room server is defined by several components, which are systems that enable features, some of these are optional and some are required.

Required

Optional

Privacy modes

A room server should allow the room admin or a moderator to configure which users can become internal user.

Specification

There are three strategies recommended as policies to join the room, known as privacy modes:

Joining: To become a member of the room, peers need to join the room.

Config database

The configuration database holds basic administrative data, readable only by admins and (indirectly via the dashboard) by moderators.

Specification

The database should contain these data points:

Web Dashboard

This is a WWW interface that allows moderators to sign-in and perform some privileged actions. The sign-in method SHOULD be SSB HTTP Authentication but it MAY be username/password or other methods. Internal users can also sign-in and perform basic actions such as create invites for other users to join.

Specification

The dashboard grants moderators with features and powers such as:

The dashboard grants internal users basic features such as:

Security considerations

HTTPS vulnerabilities

Typically SSB has not relied on the certificate architecture underlying TLS, and has had no interoperability with HTTPS. Since rooms 2.0 rely on HTTPS, then the vulnerabilities inherent in TLS, such weak certificate authorities that can enable man-in-the-middle attacks. In such scenarios, with room servers there would be possibility for man-in-the-middle attacks when claiming invites (redirecting to another multiserver address), when resolving aliases (impersonating the alias owner), or when performing sign-in with SSB identities.

To mitigate these types of attacks, implementations and deployments of rooms should make a conscious choice of a trustworthy certificate authority.

Malicious moderator

Moderators obviously hold some power, and this power may be abused through unfair blocks, unfair revoking of aliases. In many cases, fairness is subjective, and is understood to be an essential compromise of having moderation to begin with. So in this section we will focus our attention on unusual security issues with moderation.

A moderator has the right to nominate other internal users to become moderators, and this could lead to a proliferation of moderators, which increases the possibility that one of these moderators abuses their powers. On the other hand, there has been many maintainers and npm owners in the SSBC (e.g. 32 GitHub org members and 17 npm owners for the cornerstone ssb-db package), we also know that the presence of many moderators may also help to decrease the possibility of abuse, because asymmetry of privilege is reduced.

Participation

Before peers can connect to each other via a room server, they first need to become members, i.e. internal users. This section describes the different protocols used for establishing internal user participation.

Joining

"Joining a room" means the process where an external user becomes an internal user.

Specification

The joining process is different for each Privacy mode:

To summarize, in Community mode, all internal users can create invites while in Restricted mode only moderators can. Open mode means there always is an invite for all the users in the room.

Internal user registry

The internal user registry is a database the room manages, keeping records of which SSB users are internal users. It is a simple list or table, where each entry refers to an internal user, and must contain at least the SSB ID for that user.

Internal user authentication

In rooms where the privacy mode is not open, not all SSB users who connect to the room are internal users. The room thus needs a way to authenticate the user before granting them a tunnel address.

Specification

When the room receives an incoming secret-handshake connection from Alice, it checks the internal user registry, looking for the entry corresponding to Alice's ID. If there is an entry, Alice is recognized as an internal user, granting her a tunnel address. Otherwise, the room recognizes Alice as an external user and does not grant Alice a tunnel address.

In either case, whether Alice is an internal or external user, the secret-handshake and muxrpc connection is allowed to remain up, because external users are allowed to consume aliases and create tunneled connections with internal users. The exception to the above is when the room is in Restricted mode, in which case only internal users are allowed to maintain a secret-handshake and muxrpc connection.

Security considerations

Malicious room admin

The room software could be modified by the room admin to not authenticate some users as internal users.

Invites

When joining a Community room or Restricted room, internal users create invites. An invite can be sent to anyone who is not yet an internal user, and who can then "claim" the invite in order to become a new internal user of the room.

A room server SHOULD employ SSB HTTP Invites.

Tunnel addresses

To establish a tunneled connection, the peer initiating it must know the tunnel address of the peer at the other side of the tunnel.

Specification

A tunnel address is a string conforming to the multiserver-address grammar. We say that "room M grants peer A a tunnel address" when room M allows other peers to request and establish tunneled connections with peer A, using the tunnel address to identify peer A.

It consists of three parts and : as separators in between:

Example

Without spaces nor newlines:

tunnel:@7MG1hyfz8SsxlIgansud4LKM57IHIw2Okw
/hvOdeJWw=.ed25519:@1b9KP8znF7A4i8wnSevBSK
2ZabI/Re4bYF/Vh3hXasQ=.ed25519

The tunnel address, being a multiserver address, can also contain a transform section, such as the common shs transform (without spaces nor newlines):

tunnel:@7MG1hyfz8SsxlIgansud4LKM57IHIw2Okw
/hvOdeJWw=.ed25519:@1b9KP8znF7A4i8wnSevBSK
2ZabI/Re4bYF/Vh3hXasQ=.ed25519~shs:1b9KP8z
nF7A4i8wnSevBSK2ZabI/Re4bYF/Vh3hXasQ=

Tunneled connection

A tunneled connection is an indirect connection between two peers assisted by an intermediary peer. Ideally, two peers could always connect with each other directly, but they often have unstable IP addresses behind NATs and firewalls, making it difficult to consistently and reliably establish connections. The purpose of the intermediary peer is to improve connection reliability, because these intermediary peers can be privileged nodes with public IP addresses, such as from hosting services.

Specification

Tunneled connections in SSB originated from the proof-of-concept ssb-tunnel module. Suppose A and B are clients of a intermediary server M. Peer A creates a conventional handshake connection to M, and waits to receive tunnel connections. Peer B creates a conventional secret handshake connection to M, and then requests a tunneled connection to A through that conventional connection (B-M). Then, M calls A, creating a tunneled connection where one end is attached to A and the other end is attached to B's request. Finally, B uses the secret handshake to authenticate A.

Notice that for the intermediary M, peer A is the server and B is the client (client calls, server answers) but M is just the portal. The tunneled connection is inside the outer (conventional) connections, which means it is encrypted twice with box stream. This means A and B can mutually authenticate each other, and M cannot see the content of their connection.

Diagram:

,---,      ,---,     ,---,
|   |----->|   |<----|   |
| A |<=====| M |<====| B |
|   |----->|   |<----|   |
`---`      `---`     `---`

The arrows represent the direction of the connection – from the client, pointing to the server. Notice the M<=B connection is the same direction as the M<-B outer connection, but the A<=M connection is the opposite direction as the A->M outer connection.

Security considerations

Malicious room admin

The room admin could log and track all connection sessions for every tunneled connection, thus tracking the IP addresses, timestamps, durations, and bandwidth of interactions between internal users. The room admin could track which SSB users are interested in connecting with internal users, i.e. they can gather social interest metadata, which could be used to create a draft of a portion of the social graph.

That said, because of encrypted tunneled secret-handshake channels, the room admin could not know the contents of data transmitted between the internal users.

Tunneled authentication

Tunneled authentication is about making sure that SSB peers on the opposite end of a tunneled connection only allow the connection to occur if they follow the peer on the other side. Thus we need a way for peers to know who wants to open a tunneled connection and we should facilitate mutual follows to occur so that peers only create tunneled connections imbued with mutual interest.

Specification

Tunneled friend authentication is an algorithm or protocol that applies automatically without any user input from either end of the secret-handshake channel. This protocol should not apply for the intermediary peer, that is, the room server.

When Alice receives a tunneled secret-handshake incoming connection from Bob, she automatically allows it if Alice checks that she follows Bob, or automatically cancels the connection if Alice checks that she does not follow Bob (or blocks Bob). Same is true reciprocically: Bob applies this rule for incoming connections from Alice.

Thus tunneled authentication requires mutual follows ("friendship") before establishing a functioning tunneled connection.

When a denial of connection occurs, the peer that received the connection should be able to see (and thus locally log): (1) SSB ID of the intermediary peer (room) used, (2) SSB ID of the origin peer behind the intermediary, (3) (optionally) the address (tunnel address or alias endpoint URL) of the origin peer.

The user that received the denied connection can then see this fact in their SSB app, and then they can make a conscious choice to either (1) follow the origin peer, or (2) connect to the origin peer (if (3) from the previous paragraph existed), or both.

Implementation notes

Note that in current room server implementation in JavaScript, opts.origin in the room is calculated from secret-handshake, so it can be trusted to be authentic.

For the next version of rooms, if we want opts.origin to also contain the origin peer's address (ssb-tunnel address or alias endpoint), then we need other means of verifying that the origin address is authentic. E.g. if it's an alias endpoint URL, maybe the receiving peer visits the alias JSON endpoint then consumes the alias, or maybe the receiving peer takes the ssb-tunnel address and verifies that the ID matches with the secret-handshake-given ID.

Metadata API

Clients, whether internal or external users, may need to know additional information about the room before interacting with it. For instance, they may need to know whether they are an internal user or not, and they may need to know what features the room has currently enabled.

Specification

The muxrpc API room.metadata is an async method that returns a JSON object listing information about the room.

Input: zero arguments required

Output: JSON body type, with the following JSON schema

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-metadata",
  "type": "object",
  "properties": {
    "name": {
      "title": "Name of this room",
      "description": "The domain or hostname or arbitrary name of the room server",
      "type": "string"
    },
    "membership": {
      "title": "Membership",
      "description": "Whether or not the client calling this muxrpc method is recognized as an internal user",
      "type": "boolean"
    },
    "features": {
      "title": "Features",
      "description": "A list of features supported by this room",
      "type": "array",
      "uniqueItems": true,
      "items": {
        "enum": ["tunnel", "room1", "room2", "alias", "httpAuth", "httpInvite"]
      }
    }
  },
  "required": ["name", "membership", "features"]
}

The features array is particularly important, as it flags which features clients can use on the room. The semantics of each value in the enum are listed below:

Attendants API

Internal users can discover about the presence of other internal users currently online at the room. This gives them the opportunity to choose to establish a tunneled connection.

Specification

The muxrpc API room.attendants is a source method that streams JSON objects of three different schemas: state objects, joined objects, and left objects.

There are no input arguments expected on this method.

State objects

When the user subscribes to the room.attendants stream, the first event MUST be of type "state", matching the JSON schema below:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-attendants-state",
  "type": "object",
  "properties": {
    "type": {
      "title": "Event type",
      "type": "string",
      "pattern": "^(state)$"
    },
    "ids": {
      "title": "SSB IDs of attendants",
      "description": "A list of SSB IDs of all internal users currently online",
      "type": "array",
      "uniqueItems": true,
      "items": {
        "type": "string"
      }
    }
  },
  "required": ["type", "ids"]
}

Joined objects

Whenever an internal user becomes online in the room, an event matching the following JSON schema below MUST be sent through the stream:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-attendants-joined",
  "type": "object",
  "properties": {
    "type": {
      "title": "Event type",
      "type": "string",
      "pattern": "^(joined)$"
    },
    "id": {
      "title": "SSB ID",
      "description": "SSB ID of the attendant who just joined",
      "type": "string"
    }
  },
  "required": ["type", "id"]
}

Left objects

Whenever an internal user ceases to be online in the room, an event matching the following JSON schema below MUST be sent through the stream:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-attendants-left",
  "type": "object",
  "properties": {
    "type": {
      "title": "Event type",
      "type": "string",
      "pattern": "^(left)$"
    },
    "id": {
      "title": "SSB ID",
      "description": "SSB ID of the attendant who just left",
      "type": "string"
    }
  },
  "required": ["type", "id"]
}

Alias

An alias (also known as "room alias") is a string that identifies an internal user, designed to be short and human-friendly, similar to email addresses and Mastodon WebFinger addresses. The purpose of aliases is to improve the user experience of accurately (1) identifying the internal user and (2) locating the internal user at a room server for the purpose of establishing a connection with them.

As an example, suppose Alice is an internal user of the room "Scuttlebutt EU". The room's domain is scuttlebutt.eu and Alice's alias is alice. Alice's alias endpoint is thus alice.scuttlebutt.eu.

In short,

Alias string

An internal user's alias, also known as "alias string", is used to uniquely (unique within the room server only) identify that internal user. This string is useful only within the context of the room, i.e. not globally identifiable.

Example

Suppose Alice is an internal user of the room "Scuttlebutt EU". Alice's alias could be one of these strings (non-exhaustive list):

Specification

The string should satisfy the same rules as domain "labels" as defined in RFC 1035.

Alias registration

An internal user who does not have an alias in the current room server can choose to register an alias. Not all internal users need to have aliases, so the process described here is optional.

Specification

  1. An internal user with SSB ID feedId and a room server with SSB ID roomId are connected to each other via secret-handshake
  2. The internal user chooses a alias as a candidate alias string
  3. The internal user calls a specific muxrpc async API room.registerAlias(alias, signature) where signature is a cryptographic signature of the string =room-alias-registration:${roomId}:${feedId}:${alias} using feedId's cryptographic keypair, read more about it in the alias database spec
  4. The room, upon receiving the room.registerAlias muxrpc call, checks whether that alias is valid (see spec in Alias string)
    1. If it is invalid, respond room.registerAlias with an error
    2. Else, proceed (below)
  5. The room checks whether there already exists an entry in the Alias database with the key alias
    1. If there is, respond room.registerAlias with an error
    2. Else, proceed (below)
  6. The room adds an entry to its Alias database for key=alias & value=feedId+sig
  7. The room responds room.registerAlias with a string containing the Alias endpoint URL for the newly registered alias, indicating success
  8. The internal user receives the room's response to room.registerAlias
    1. If it is an error, then (optionally) display a user interface failure to register the alias
    2. If it is a successful url string, then the internal user MAY publish an SSB msg of type about with a field listing all its aliases for various rooms, where this specific url is included. The specific schema of the message type is an application-level concern

The above algorithm is also provided below as a UML sequence diagram:

sequenceDiagram participant U as SSB peer participant R as Room server U->>R: (muxrpc async) `room.registerAlias(alias, signature)` alt `alias` is an invalid alias string
or already taken in the alias database
or other errors R-->>U: Respond room.registerAlias with an error opt U->>U: Display user interface error end else else R->>R: Adds an entry to
its alias database R-->>U: Respond `room.registerAlias` with a `url` string U->>U: Publishes an SSB
msg of type
`about` end

Security considerations

Malicious internal user

A malicious internal user could take many or all possible aliases in case the room accidentally allows such malicious user to become an internal user. Arguably, some room implementations could choose to allow only one alias per internal user, and that would still be compliant with this spec.

Malicious room admin

The room admin could reply with errors when technically the muxrpc should have succeeded, e.g. pretending that the alias candidate is invalid or pretending that it's already registered.

Alias revocation

When an internal user who has registered no longer wishes to have that alias associated with them anymore, they can perform alias revocation to remove that alias from the alias database.

Specification

  1. An internal user with SSB ID feedId and a room server with SSB ID roomId are connected to each other via secret-handshake
  2. The internal user calls a specific muxrpc async API room.revokeAlias(alias, callback)
  3. The room, upon receiving the room.revokeAlias muxrpc call, checks whether there exists an entry in the Alias database for alias
    1. If there is no entry, respond room.revokeAlias with an error
    2. Else, if there exists an entry for alias but it is not owned by feedId, respond room.revokeAlias with an error
    3. Else, proceed (below)
  4. The room removes the entry from the Alias database associated with feedId
  5. The room responds room.revokeAlias with true, indicating success
  6. The internal user receives the room's response to room.revokeAlias
    1. If it is an error, then (optionally) display a user interface failure to revoke the alias
    2. If it is true, then publish an SSB msg of type about with a field listing all its aliases for various rooms, where this specific alias is no longer listed. The specific schema of the message type is an application-level concern

The above algorithm is also provided below as a UML sequence diagram:

sequenceDiagram participant U as SSB peer participant R as Room server U->>R: (muxrpc async) `room.revokeAlias(alias)` alt `alias` does not exist, or other errors R-->>U: Respond room.revokeAlias with an error opt U->>U: Display user interface error end else else R->>R: Remove the entry in
the alias database R-->>U: Respond room.revokeAlias with `true` U->>U: Publishes an SSB
msg of type
`about` end

Security considerations

Malicious room admin

The room admin could refuse to remove the database entry, or could delete the database entry at will (before the internal user performs revocation). In other words, the internal user does not ultimately have power over the deletion of the alias entry from the alias database, it must trust the room admin regarding deletion.

Alias consumption

When an SSB user (external or internal) is connected to the room, and knows of another internal user's alias, they can perform alias consumption. After consumption is completed successfully, they authentically obtain the target user's SSB ID and can use it to start a tunneled connection.

Specification

The input for the consumption algorithm is the response from the web endpoint, which is (either through JSON or SSB URI): the room's multiserver address, roomId, userId, alias, and signature.

  1. The SSB user verifies that the signature authentically matches roomId, userId and alias
    1. If it is an invalid signature, interrupt alias consumption with a failure indicating that the alias association to the internal user userId was probably forged
    2. Else, proceed (below)
  2. The SSB user acting as a client connects to the room's address and establishes a muxrpc connection
  3. The client can now use userId to initiate a tunneled connection with them
  4. (Optional and recommended) The client follows the userId, see tunneled authentication

Web endpoint

Once an alias is registered, it enables any web user to visit a web endpoint on the room server dedicated to that alias, for the purpose of telling the visitor what SSB ID does the alias resolve to, and with instructions on how to install an SSB app if the visitor doesn't have it yet.

The goal of this endpoint is to help any SSB user locate and identify the alias' owner by resolving the alias to: (1) the room's multiserver address, (2) the owner's SSB ID, and (3) a cryptographic signature that proves the owner associated themselves with that alias. This web endpoint is valuable to onboard new SSB users being invited by an internal user.

Prior art: This endpoint should be in many ways similar to the Telegram https://t.me/example service for the username @example, also capable of redirecting the web visitor to a scheme tg URI tg://resolve?domain=example, which Telegram apps know how to parse and open the target user's profile screen.

Specification

This specification does not apply if the privacy mode is Restricted. This web endpoint is available only if the privacy mode is Open or Community.

If the alias ${alias} is registered at the room ${roomHost} for a certain ${userId}, then the room's HTTP endpoint reserved for the alias SHOULD be the wildcard subdomain URL https://${alias}.${roomHost} but it MAY be https://${roomHost}/${alias}.

The HTML response then:

As an additional endpoint for programmatic purposes, if the query parameter encoding=json is added to the alias endpoint (for illustration: https://${alias}.${roomHost}?encoding=json), then, in successful responses, the JSON body MUST conform to the following schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://github.com/ssb-ngi-pointer/rooms2#alias-json-endpoint-success",
  "type": "object",
  "properties": {
    "status": {
      "title": "Response status tag",
      "description": "Indicates the completion status of this response",
      "type": "string",
      "pattern": "^(successful)$"
    },
    "multiserverAddress": {
      "title": "Multiserver address",
      "description": "Should conform to https://github.com/ssbc/multiserver-address",
      "type": "string"
    },
    "roomId": {
      "title": "Room ID",
      "description": "SSB ID for the room server",
      "type": "string"
    },
    "userId": {
      "title": "User ID",
      "description": "SSB ID for the user owning the alias",
      "type": "string"
    },
    "alias": {
      "title": "Alias",
      "description": "A domain 'label' as defined in RFC 1035",
      "type": "string"
    },
    "signature": {
      "title": "Signature",
      "description": "Cryptographic signature covering the roomId, the userId, and the alias",
      "type": "string"
    }
  },
  "required": [
    "status",
    "multiserverAddress",
    "roomId",
    "userId",
    "alias",
    "signature"
  ]
}

In failed responses, the JSON body MUST conform to the following schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://github.com/ssb-ngi-pointer/rooms2#alias-json-endpoint-error",
  "type": "object",
  "properties": {
    "status": {
      "title": "Response status tag",
      "description": "Indicates the completion status of this response",
      "type": "string"
    },
    "error": {
      "title": "Response error",
      "description": "Describes the specific error that occurred",
      "type": "string"
    }
  },
  "required": [
    "status",
    "error"
  ]
}

Example

Suppose the alias is bob, registered for the user ID @yVQxFxzeRQ13DQ813hf8G20U5z5I/nkNDliKeSs/IpU=.ed25519 at the room with host name scuttlebutt.eu. Then the alias endpoint https://bob.scuttlebutt.eu responds with HTML containing the following SSB URI:

ssb:experimental?action=consume-alias&multiserverAddress=net%3Ascuttlebutt.eu%3A8008~shs%3Azz%2Bn7zuFc4wofIgKeEpXgB%2B%2FXQZB43Xj2rrWyD0QM2M%3D&alias=bob&roomId=%40zz%2Bn7zuFc4wofIgKeEpXgB%2B%2FXQZB43Xj2rrWyD0QM2M%3D.ed25519&userId=%40yVQxFxzeRQ13DQ813hf8G20U5z5I%2FnkNDliKeSs%2FIpU%3D.ed25519&signature=EiEgn%2Fh2lKoaz28ggKBod6havJNKapRKCmXQ%2Ft%2F4KS1gY4T6zPXWhw6kTaglt8vDJZW%2BjJRJvfB4Rryhl0njCg%3D%3D.sig.ed25519

The JSON endpoint https://bob.scuttlebutt.eu/?encoding=json would respond with the following JSON:

{
  "status": "successful",
  "multiserverAddress": "net:scuttlebutt.eu:8008~shs:zz+n7zuFc4wofIgKeEpXgB+/XQZB43Xj2rrWyD0QM2M=",
  "roomId": "@zz+n7zuFc4wofIgKeEpXgB+/XQZB43Xj2rrWyD0QM2M=.ed25519",
  "userId": "@yVQxFxzeRQ13DQ813hf8G20U5z5I/nkNDliKeSs/IpU=.ed25519",
  "alias": "bob",
  "signature": "EiEgn/h2lKoaz28ggKBod6havJNKapRKCmXQ/t/4KS1gY4T6zPXWhw6kTaglt8vDJZW+jJRJvfB4Rryhl0njCg==.sig.ed25519"
}

Security considerations

Malicious web visitor

A web visitor, either human or bot, could attempt brute force visiting all possible alias endpoints, in order to build a dataset of all SSB IDs and claimed aliases gathered at this room, potentially tracking profiles of these SSB IDs. Malicious web visitors can also attempt to connect with these target IDs as victims, and may use social engineering or impersonation tactics during tunneled authentication.

Malicious room admin

The room admin could tamper with the alias database and provide fake information on this web endpoint, e.g. that a certain alias was claimed by a certain users. Although the database signature exists to prevent this type of tampering, it is only verified when performing alias consumption. For web visitors who only want to know which SSB ID corresponds to an alias, and only that, these visitors must trust the room administrator, who could provide inauthentic information.

Alias database

This is a database that stores all aliases that were registered by internal users.

Example

The following is a mock up of a key-value store:

Key Value
alice @FlieaFef19uJ6jhHwv2CSkFrDLYKJd/SuIS71A5Y2as=.ed25519 plus signature
bob @25WfId3Vx/gyMAZqCyZzhtW4iPtUVXB/aOMYbq44P4c=.ed25519 plus signature
carla @dRE+jzKo0VWX6JbcSVATyOvFlbjCNwPWNzQLkTGenac=.ed25519 plus signature
daniel @SMMgb4bZAgRgtAPdMw4loQeZL9lQgsRDi+xin0ZDzAg=.ed25519 plus signature

Specification

This can be a simple persistent key-value store, such as Leveldb.

The signature is applied on the following string: =room-alias-registration:${roomId}:${userId}:${alias}, known as the Alias confirmation, see example (without spaces nor newlines):

=room-alias-registration:@51w4nYL0k7mRzDGw20KQqCjt35
y8qLiBNtWk3MX7ppo=.ed25519:@FlieaFef19uJ6jhHwv2
CSkFrDLYKJd/SuIS71A5Y2as=.ed25519:alice

where

The purpose of a cryptographic signature on the combined roomId & userId & alias is to make sure that the Room admin cannot tamper with the database to delegitimize its contents. This means that each key-value pair is certainly authored by the declared SSB ID, that is, neither the key (the alias) nor the value (the SSB ID) was modified by the Room admin.

Security considerations

Malicious room admin

The room admin can freely read or write to this database, they can create new entries, and so forth. If they modify an entry and thus break the validation of the signatures, other SSB users can detect this when verifying the signatures.

Thus the admin cannot effectively:

But the admin can:

Malicious moderator

Similar considerations as with the room admin, but less powers. The malicious moderator cannot do the actions that the room admin cannot do (otherwise moderators would have more power than admins), but the one thing moderators can do is:

Appendix

List of new muxrpc APIs

List of new SSB URIs