aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-common/src/meshbay_common/device.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-common/src/meshbay_common/device.py')
-rw-r--r--packages/meshbay-common/src/meshbay_common/device.py39
1 files changed, 39 insertions, 0 deletions
diff --git a/packages/meshbay-common/src/meshbay_common/device.py b/packages/meshbay-common/src/meshbay_common/device.py
index 8951dbb..cfa8dd6 100644
--- a/packages/meshbay-common/src/meshbay_common/device.py
+++ b/packages/meshbay-common/src/meshbay_common/device.py
@@ -36,6 +36,7 @@ import hashlib
DEVICE_REQUEST_PREFIX = b"meshbay:device_req:v1"
DEVICE_ADD_PREFIX = b"meshbay:device_add:v1"
+DEVICE_HELLO_PREFIX = b"meshbay:device_hello:v1"
# Same as the join and admin transcripts: interactive exchanges that complete in
# milliseconds, so anything older is a replay.
@@ -123,3 +124,41 @@ def device_add_transcript(
nonce_node,
str(ts).encode(),
])
+
+
+def device_hello_transcript(
+ node_pk_b64: str,
+ group_id: str,
+ user_id: str,
+ pk_ed25519_b64: str,
+ nonce_node: bytes,
+ ts: int,
+) -> bytes:
+ """
+ Signed by the device on an already-authenticated connection, saying **which
+ of the account's devices this connection is**.
+
+ The handshake proves membership of a group (a GEK-HMAC) and carries an
+ account from the hub's token; it proves nothing about *which* device is
+ talking. The node needed that the moment one account could hold several:
+ `_load_pinned_pk` was resolving "this account's oldest live device" and
+ recording it as the uploader of every file, so a phone's uploads were
+ attributed to a laptop.
+
+ Additive and optional. A client that does not send it leaves the node where
+ it was, which is why this could ship without a breaking protocol change —
+ but a node that *has* been told refuses a later claim to be a different
+ device on the same connection.
+
+ `nonce_node` is this connection's handshake nonce, so the signature cannot
+ be lifted onto another connection, and `node_pk` binds it to one node —
+ the same rule as every other transcript here.
+ """
+ return _pack(DEVICE_HELLO_PREFIX, [
+ node_pk_b64.encode(),
+ group_id.encode(),
+ user_id.encode(),
+ pk_ed25519_b64.encode(),
+ nonce_node,
+ str(ts).encode(),
+ ])