Skip to content

feat: http server based key package registry#124

Open
kaichaosun wants to merge 5 commits into
mainfrom
http-key-registry
Open

feat: http server based key package registry#124
kaichaosun wants to merge 5 commits into
mainfrom
http-key-registry

Conversation

@kaichaosun
Copy link
Copy Markdown
Contributor

@kaichaosun kaichaosun commented Jun 1, 2026

Changes:

  • Adds a standalone HTTP service bin/keypackage-registry that holds MLS KeyPackages so clients can add a contact by account_id without out-of-band bundle exchange.
  • Adds a matching HttpRegistry client in extensions/components and an opt-in --registry-url flag on chat-cli. Without the flag, behavior is unchanged.
  • Throwaway by design: scheduled to be replaced by λLEZ-based discovery in v0.3.

Fix #110.

@kaichaosun kaichaosun force-pushed the http-key-registry branch from 33f228f to bb1beff Compare June 1, 2026 04:10
@kaichaosun kaichaosun force-pushed the http-key-registry branch from bb1beff to 9a01fac Compare June 1, 2026 04:37
@kaichaosun kaichaosun force-pushed the http-key-registry branch from 53c45c7 to e0f6054 Compare June 1, 2026 05:54
@kaichaosun kaichaosun force-pushed the http-key-registry branch from 3705d27 to 3683ba5 Compare June 1, 2026 08:42
Comment thread extensions/components/src/lib.rs

```json
{
"account_id": "user-chosen label",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Pebble] Account Id cannot be a user-chosen label. It must be a static, string derived from the account


**Server is dumb storage.** Submissions are stored without verification. Bundles carry a self-signature by the device key over `(account_id || device_pubkey || key_package || ts_le)`; consumers verify it on retrieve. This catches a replay attack where someone copies a victim's bundle and re-posts it under a different `account_id` — the signature commits to the original `account_id` and won't verify against the new one.

The self-signature does **not** prove that `device_pubkey` is actually authorized for `account_id` (an attacker can mint their own keys and sign anything). That impersonation gap closes once λLEZ provides the on-chain authorization mapping in v0.3.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here is that this registry is attempting to solve two problems at once.

Account registration (The association of Installations/DeviceKeys into a single account) and the caching of KeyPackages from a single DeviceKey.

Solving both at the same time adds more complication. I'd focus only on the KeyPackage caching for now, then address Accounts in a later PR.

```

`signature` MUST be Ed25519 by `device_pubkey` over the byte concatenation
`account_id || device_pubkey || key_package || timestamp_ms.to_le_bytes()`.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Dust] Having the signature being defined over byte concat, and the "Package" being transported to the server being defined as base64 encoded JSON, makes validating the payload more difficult.

Conside symmetry, by using a well defined binary payload, with an associated signature.

```json
{
"account_id": "user-chosen label",
"device_pubkey": "base64(32-byte ed25519 verifying key)",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[?] What key does this correspond to?

Comment on lines +52 to +55
The server validates only basic shapes (`device_pubkey` 32 bytes, `signature`
64 bytes, valid base64). It does **not** verify the signature — verification
happens client-side on retrieve. Returns `204 No Content` on success, `400`
on shape errors.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[?] Is there a reason why the serve couldn't validate signatures in this test case?

Comment on lines +57 to +60
### `GET /v0/keypackage/{account_id}`

Returns the most recently submitted bundle for that id, across all devices.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[?] What is considered a bundle in this case?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue with querying by account_id is that key-packages are single use, per group. If one of the keypackages have already been used, its harder to request another another one.

Comment on lines +1 to +4
[package]
name = "keypackage-registry"
version = "0.1.0"
edition = "2024"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need need to be deployed and managed in its own repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Testnet KeyPackage Registry

2 participants