Spracherkennung für: .proto vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
// ## Device Join Protocol
//
// This protocol specifies how to add a new device to an existing device group.
//
// ### Terminology
//
// - `ED`: Existing device
// - `ND`: New device to be added
//
// ### Blobs
//
// For binary data, the usual Blob scheme is being used by ED. However, instead
// of transferring Blob data via the Blob server, the data is transmitted in
// form of a `common.BlobData` message ahead of a message referencing that Blob
// by the associated Blob ID.
//
// ND is supposed to cache received `common.BlobData` until it can associate the
// data to a Blob referencing its ID. Once the rendezvous connection has been
// closed, any remaining cached `common.BlobData` can be discarded.
//
// ### Protocol Kickoff Flow
//
// ND or ED may choose to start the protocol. If ND starts the protocol it is
// _requesting to join the device group_. If ED starts the protocol it is
// _offering to join the device group_.
//
// If ED started the protocol:
//
// - `variant` must be set to _offer to join the device group_.
// - ED takes the role of RID
// - ND takes the role of RRD
//
// If ND started the protocol:
//
// - `variant` must be set to _request to join the device group_.
// - ND takes the role of RID
// - ED takes the role of RRD
//
// #### Connection Setup
//
// RID creates a `rendezvous.RendezvousInit` by following the Connection
// Rendezvous Protocol. It wraps it in a `url.DeviceGroupJoinRequestOrOffer` and
// offers it in form of a URL or a QR code.
//
// RRD scans the QR code or decodes the URL and then parses the
// `url.DeviceGroupJoinRequestOrOffer`. It will then receive the data over a
// sufficiently secure channel (e.g. a QR code). Once decoded, the enclosed
// `rendezvous.RendezvousInit` must be handled according to the Connection
// Rendezvous Protocol.
//
// Once the Connection Rendezvous Protocol has established at least one
// connection path, ED waits another 3s or until all connection paths have been
// established. Nomination is then done by ED following the Connection
// Rendezvous Protocol.
//
// Note that all messages on the nominated connection path must be end-to-end
// encrypted as defined by the Connection Rendezvous Protocol. All transmitted
// messages are to be wrapped in:
//
// - `NdToEd` when sending from ND to ED, and
// - `EdToNd` when sending from ED to ND.
//
// #### Device Join Flow
//
// As soon as one of the connection paths has been nominated by ED, both devices
// must calculate the Rendezvous Path Hash (RPH) as defined by the Rendezvous
// Protocol and display it to the user.
//
// ED must ask the user for confirmation that RPH is equal on both devices. The
// exact comparison mechanism is an implementation detail. If the user does not
// confirm that RPH is equal on both devices, the process must be aborted.
//
// After confirmation, ED must stop displaying RPH and send a `Begin` message to
// start the device join process.
//
// ED ------- Begin ------> ND [1]
//
// ND can now stop displaying RPH.
//
// ED -- common.BlobData -> ND [0..N]
// ED --- EssentialData --> ND [1]
//
// Once ND successfully registered itself on the Mediator server, it sends a
// `Registered` message.
//
// ED <---- Registered ---- ND [1]
//
// ND may now either close the connection or leave it open to transition to the
// History Exchange Protocol. Any further messages ED receives from ND will
// transition into the History Exchange Protocol.
//
// ### Security
//
// The `url.DeviceGroupJoinRequestOrOffer` must be exchanged over a sufficiently
// secure channel. A QR code is considered sufficiently secure in a _safe
// space_. If this can be ensured by the user, ensuring that the Rendezvous Path
// Hash (RPH) is equal on both devices is not strictly necessary.
//
// If an attacker is however able to capture the
// `url.DeviceGroupJoinRequestOrOffer`, the security of the protocol relies on
// the user ensuring that RPH is equal on both devices to ensure authentication
// and mitigate the following attacks:
//
// - If ED started the protocol (offers to join the device group), comparing RPH
// is critical as otherwise the Client Key would become compromised if an
// attacker were able to make a connection faster than the victim's other
// device.
// - If ND started the protocol (requests to join the device group), comparing
// RPH is not as critical yet still vital to mitigate a more sophisticated
// attack where the attacker makes it look as if the victim is connected to
// its device group. Until the victim finds out that it isn't its device group
// (because the process is stuck on ED), the victim may potentially leak
// sensitive information by adding a contact or sending a message, etc.
// - An attacker who also controls the relay server used for connection between
// the victim's two devices could run a full MITM attack. Comparing RPH here
// is critical to ensure that the victim's two devices have established an
// end-to-end encrypted communication channel between each other.
//
// Letting ND start the protocol is considered more secure because of the above
// implications.
//
// ED is always required to let the user confirm the equality of RPH on both
// devices because it is ED who is to transmit the highly sensitive information.
//
// To prevent phishing attacks of a malicious web app claiming to be a Threema
// App (typo squatting), the CORS `Access-Control-Allow-Origin` of any WebSocket
// rendezvous relay server must be set to the bare minimum required by the use
// case, so that a connection cannot be established. However, phishing
// protection against a malicious non-web app claiming to be a Threema App is
// not possible.
syntax = "proto3";
package join;
option java_package = "ch.threema.protobuf.d2d.join";
import "common.proto";
import "md-d2d-sync.proto";
// Root message envelope for messages from the new device (ND) to the existing
// device (ED).
message NdToEd {
// The enveloped message
oneof content {
Registered registered = 1;
}
}
// Root message envelope for messages from the existing device (ED) to the new
// device (ND).
message EdToNd {
// The enveloped message
oneof content {
Begin begin = 1;
// A Blob that is referenced as part of `EssentialData`.
//
// When receiving this variant:
//
// 1. If `EssentialData` has been received before, close the connection and
// abort these steps.
// 2. Store the Blob data temporarily or permanently and store its
// associated Blob ID in the device's database.
common.BlobData blob_data = 2;
EssentialData essential_data = 3;
}
}
// Initial message sent by ED after nomination and user confirmation that RPH is
// identical on both devices.
//
// When creating this message, after confirmation by the user:
//
// 1. Stop displaying RPH and notify the user that the device join process is in
// progress.
// 2. Begin a transaction (scope `NEW_DEVICE_SYNC`, precondition: none) on the
// D2M connection. This transaction is to be held until the connection to ND
// drops or until a `Registered` message was received. While the transaction
// is being held, no `Reflected` and no end-to-end encrypted message coming
// from the chat server is allowed to be processed! If the D2M connection is
// lost, the established connection must also be closed, aborting any running
// steps of this protocol.
// 3. Send the `Begin` message and continue with the steps for creating
// `EssentialData`.
//
// When receiving this message:
//
// 1. If `Begin` has been received before, close the connection and abort these
// steps.
// 2. Stop displaying RPH and notify the user that the device join process is in
// progress.
message Begin {}
// Essential data ND needs to be able to participate in the device group.
//
// Note: The transmitted used nonces are hashed with HMAC-SHA256 using the
// identity as _key_.
//
// When creating this message:
//
// 1. Gather all blobs referenced for the user's profile picture, contact
// profile pictures, etc. and send them as `common.BlobData` before this
// message.
// 2. Send the gathered `EssentialData`.
//
// When receiving this message:
//
// 1. If `EssentialData` has been received before, close the connection and
// abort these steps.
// 2. If any Blob ID is missing from the previously received set of
// `common.BlobData`, close the connection and abort these steps.
// 3. Store the data in the device's database.
// 4. Generate a random D2M Device ID and a random CSP Device ID and store both
// in the device's database.
// 5. Establish a D2M connection by connecting to the provided mediator server.
// 6. Wait until the `ServerInfo` has been received on the D2M connection.
// Validate that the provided `DeviceSlotState` is `NEW`. Otherwise, close
// both the D2M connection (normally) and the connection to ED and abort
// these steps.
// 7. Send a `Registered` message to ED.
// 8. Ask the user whether conversation history data should be requested from
// ND:
// 1. If the user does not want to request conversation history data, wait
// until all buffered data on the connection has been written. Then, close
// the connection and abort these steps.
// 2. If the user wants to request conversation history data from ED, leave
// the connection running and start the History Exchange Protocol.
message EssentialData {
reserved 1; // Reserved for mediator server
// User's identity data
message IdentityData {
// The user's Threema ID
string identity = 1;
// The permanent client key associated to the Threema ID (32 bytes)
bytes ck = 2;
// The device cookie used by the device group for the Threema ID (16 bytes)
bytes csp_device_cookie = 3;
// The CSP server group associated to the Threema ID (1 byte)
string csp_server_group = 4;
}
IdentityData identity_data = 2;
// Threema Work credentials
//
// Required for a Threema Work app. Must not be present in a Threema consumer
// app.
sync.ThreemaWorkCredentials work_credentials = 12;
// Device group data
message DeviceGroupData {
// The device group key (32 bytes)
bytes dgk = 1;
}
DeviceGroupData device_group_data = 3;
// User's profile
sync.UserProfile user_profile = 4;
// Shared settings
sync.Settings settings = 5;
// MDM parameters
//
// Optional for a Threema Work app. Must not be present in a Threema consumer app.
//
// [//]: # "TODO(SE-307): Make this required for Threema Work!"
sync.MdmParameters mdm_parameters = 6;
// Contacts
message AugmentedContact {
// The contact's data.
sync.Contact contact = 1;
// Unix-ish timestamp in milliseconds when the conversation with this
// contact was last updated.
//
// Optional if no conversation exists for this contact.
optional uint64 last_update_at = 2;
}
repeated AugmentedContact contacts = 7;
// Groups
message AugmentedGroup {
// The group's data.
sync.Group group = 1;
// Unix-ish timestamp in milliseconds when the conversation with this
// group was last updated.
uint64 last_update_at = 2;
}
repeated AugmentedGroup groups = 8;
// Distribution lists
message AugmentedDistributionList {
// The distribution list's data.
sync.DistributionList distribution_list = 1;
// Unix-ish timestamp in milliseconds when the conversation of this
// distribution list was last updated.
uint64 last_update_at = 2;
}
repeated AugmentedDistributionList distribution_lists = 9;
// Hashed nonces that were used for CSP messages.
repeated bytes csp_hashed_nonces = 10;
// Hashed nonces thate were used for D2D messages.
repeated bytes d2d_hashed_nonces = 11;
}
// Lets ED know that ND has received all essential data and successfully
// registered itself on the mediator server.
//
// When receiving this message:
//
// 1. Commit the transaction on the D2M connection. From this point on,
// processing `Reflected` and end-to-end encrypted message coming from the
// chat server is allowed again.
// 2. Wait for ND to either close the connection or for ND to request
// conversation history data. Any further messages from ND will move into
// the History Exchange Protocol.
message Registered {}
[Dauer der Verarbeitung: 0.27 Sekunden, vorverarbeitet 2026-04-27]