Skip to content

Define a less target-revealing KeyPackage discovery profile #415

Open

Description

@Datawav

Summary

Marmot's Nostr KeyPackage discovery flow is account-targeted: an inviter resolves one account's kind 10002 relay list and then fetches that account's kind 30443 events from those relays. A relay or network observer can therefore learn which account is being considered for an invite from the query target and timing, even though the later Welcome and group content are encrypted.

The spec should define a compatible privacy profile for broad, batched, prefetched, or otherwise less target-shaped KeyPackage discovery. It should not promise private information retrieval or anonymity unless a deployed mechanism and useful anonymity set actually provide them.

Current behavior and threat model

  • KeyPackages are deliberately published before an inviter is online so asynchronous invites work (foundation behavior).
  • The Nostr binding tells a client to discover the target account's NIP-65 write relays and fetch that account's KeyPackages from one or more of them (publication/discovery rule).
  • Subscription rules likewise describe author-specific NIP-65 and KeyPackage lookup (fetch rules).
  • NIP-65 relay lists are public account metadata and identify the relays used for account discovery (NIP-65).

The attacker is a queried KeyPackage relay, a colluding set of account relays, or a network observer that sees a narrow lookup followed by a Welcome-shaped publish. The attacker learns contact/invite intent and timing, not MLS plaintext. Cached results reduce repeat lookups but do not by themselves hide a cold target-specific query.

Proposed invariant

Add an optional, backward-compatible KeyPackage discovery privacy profile with decision-ready requirements:

  • Discovery work SHOULD be schedulable independently from the action that needs a KeyPackage, so a cold invite need not immediately trigger a unique target lookup.
  • Clients MAY batch or prefetch bounded cohorts of accounts and cache validated fresh candidates, while preserving all existing author binding, lifetime, capability, and replacement checks.
  • The profile must define the cohort source, maximum accounts/relays/events/bytes, cache lifetime, refresh jitter, concurrency, cancellation, and behavior for a target absent from the cache.
  • Cover queries must correspond to real directory work or a declared population strategy; isolated dummy queries must not be presented as anonymity and must be bounded against relay abuse.
  • Direct account lookup remains the interoperability fallback. Clients must expose that it reveals target interest when strict privacy policy would otherwise block it.
  • PIR, oblivious proxies, or rendezvous services remain future ecosystem options, not acceptance criteria for this compatible first step.

Compatibility and migration risks

  • Broad fetches increase bandwidth, storage, battery use, relay load, and the amount of public KeyPackage metadata retained locally.
  • Contacts may publish to disjoint NIP-65 relay sets, limiting batching and enabling intersection attacks.
  • Long cache lifetimes increase stale/consumed-package failures; short lifetimes restore invite-shaped refreshes.
  • Mixed clients require direct lookup fallback and must not weaken KeyPackage validation for cache hits.

Acceptance criteria

  • The spec separates interoperability-required target lookup from the optional less-revealing discovery profile.
  • The profile defines concrete resource ceilings, refresh/cancellation semantics, cache freshness, and fallback behavior.
  • Every cached or prefetched candidate receives the same transport-author, decoded KeyPackageRef, lifetime, proof, capability, and replacement validation as a direct result.
  • A failed or cancelled prefetch cannot create group state, consume a KeyPackage, or suppress a later direct fallback.
  • Privacy text states exactly what a relay/network observer can still correlate and does not claim an anonymity set without a population/cohort model.
  • Cross-client fixtures cover cache hit, cache miss with permissive fallback, cache miss under strict policy, stale candidate rejection, disjoint relay cohorts, bounded cancellation, and direct-result equivalence.

Deduplication

Open #14 owns the general threat model, not KeyPackage discovery behavior. Closed #386 owns routing-id rotation, and closed #385 owns member-controlled media fetch tracking. Searches across open/closed Marmot and MDK issues for KeyPackage discovery batch privacy, KeyPackage fetch directory, prefetch KeyPackage, and private KeyPackage lookup found no semantic duplicate.

Activity

  1. added
    enhancementNew feature or request
    specSpec inconsistency or clarity
    on Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestspecSpec inconsistency or clarity

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions