Skip to content

feat(chat): sign user messages with device ed25519 keypair - #35

Merged
alexbelij merged 1 commit into
mainfrom
feature/chat-signing
Jul 9, 2026
Merged

feat(chat): sign user messages with device ed25519 keypair#35
alexbelij merged 1 commit into
mainfrom
feature/chat-signing

Conversation

@alexbelij

Copy link
Copy Markdown
Owner

Every user bubble in the chat now carries a small Signed · FING ERP chip. Clicking opens a 320px panel with pubkey / signature / timestamp / team_id and a live re-verification banner (green tick or red fail).

Keypair is generated once via WebCrypto ed25519, stored in IndexedDB as a non-extractable CryptoKey, and the raw 32-byte public key is mirrored to localStorage for display. Signed envelope matches the on-wire shape of src/identity/keypair.js:

{ "alg": "ed25519", "ts": "", "team_id": "", "text": "" }

Assistant replies stay unsigned — the QVAC bridge does not sign, so the demo does not fake it.

Graceful degradation: older browsers without ed25519 render a muted "Unsigned" chip. Verified end-to-end: verify(same)=true, verify(tampered)=false, verify(wrong-pub)=false, badges attach to user bubbles only, panel shows verified label.

Every user bubble in the chat now carries a small "Signed · FING ERP"
chip. The chip is a visible bridge to the on-device identity: clicking
it opens a details panel with pubkey, signature, timestamp, active
team_id, and a live re-verification banner. Assistant replies remain
unsigned — the QVAC bridge does not sign, so the demo does not fake it.

- demo/chat-signing.js: WebCrypto ed25519 keypair, persisted in
  IndexedDB as a non-extractable CryptoKey; pubkey mirrored to
  localStorage for display. Deterministic canonical payload
  ({alg, ts, team_id, text}) matches the on-wire shape of
  src/identity/keypair.js. MutationObserver decorates every user
  bubble; assistant bubbles are ignored.
- demo/styles.css: badge chip + 320px popover styles, ok/fail states
- demo/index.html: script + preload wired, ?v=33 cache-bust
- demo/sw.js: CACHE_VERSION → v33, chat-signing.js precached

Graceful degradation: browsers without ed25519 (older Safari) render
a muted "Unsigned" chip instead of failing the send.

Verified end-to-end: pubkey/sig hex lengths (64/128), verify(same)=true,
verify(tampered)=false, verify(wrong-pub)=false, badge attaches to user
bubbles only, panel shows verified label.
@alexbelij
alexbelij merged commit 2879fbe into main Jul 9, 2026
@alexbelij
alexbelij deleted the feature/chat-signing branch July 9, 2026 10:12
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.

1 participant