Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ server/.pytest_tmp/
*.db
*.sqlite
*.sqlite3
*.db-journal
blackwire.db
server/_write_test.txt

# ------------------------------
# C++ / CMake / Qt / MSVC
Expand Down
131 changes: 131 additions & 0 deletions V0.2_Update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# v0.2: Security/Privacy upgrades that won’t “horribly” hurt performance

Below is the smallest set of changes that massively improves security while keeping the system fast and deployable.

## 1) Add client message signatures (high impact, low cost)

**Goal:** a compromised server can’t impersonate users to other servers (and ideally can’t impersonate locally either).

* Each device has a long-term **signing keypair** (Ed25519).
* Every outbound message envelope includes:

* `sender_device_pubkey`
* `signature` over a canonical form of `(conversation_id, sender, recipient, timestamp, client_message_id, ciphertext_hash, …)`
* Receiver verifies signature **before** accepting.

**Performance:** trivial (Ed25519 signing/verifying is fast).
**Impact:** huge integrity/auth win immediately.

---

## 2) Replace “sealed box per message” with a session key + ratchet (moderate cost)

To call it “secure messaging”, you need at least forward secrecy. The standard answer is:

### X3DH-style handshake + Double Ratchet

* Initial key agreement uses prekeys (server stores public prekeys only)
* Session uses Double Ratchet for:

* forward secrecy
* post-compromise recovery
* message ordering / replay defenses

**Performance impact:** low to moderate (mostly constant-time crypto; the overhead is protocol complexity, not CPU).

---

## 3) Multi-device with “kick devices”

You already have a concept of `device_id`. Extend it:

* Account holds list of devices:

* `device_uid` (server-generated stable ID)
* `device_pub_sign_key`
* `device_pub_dh_key` (for sessions)
* status: active / revoked
* In client settings:

* list devices + last seen
* “kick” = server marks revoked
* Protocol:

* messages can target one or multiple devices
* ratchet sessions are per device-pair (common approach)

**Performance:** depends on “encrypt-to-how-many-devices”. Usually manageable.
**Privacy:** server still sees devices exist; content remains E2EE.

---

## 4) Fix federation TOFU: “open federation” but safer bootstrap

You want open federation, so the upgrade is:

### bind federation trust to onion identity

If Tor is enabled:

* Tie federation identity to onion service identity (or publish a signed binding)
* On first contact, the onion channel itself becomes the “trust root” (still not perfect against malicious onion takeover, but better than plain TOFU)

**Performance:** none.
**Security:** prevents silent key swaps and reduces TOFU poisoning risk.

---

## 5) Token/auth hardening (privacy + security without latency)

You correctly flagged HS256 risk and replay risk.

For v0.2:

* Move access tokens to **asymmetric signing** (EdDSA/RS256)
* Bind tokens to device:

* include `device_uid` in JWT claims
* require match at server on every request
* Short access token lifetime (e.g., 5–10 min)
* Refresh token rotation stays (good)
* Consider DPoP-style proof or per-request nonce if you want to harden replay further (optional)

**Performance:** negligible.

---

## 6) End-to-end delivery integrity (detect drops/reordering)

You said you want privacy and trust minimization; but “server can drop silently” is a real UX/security problem.

Add:

* Per-conversation monotonic counters or hash-chains:

* each message includes `prev_hash` (hash of previous accepted message)
* receiver detects gaps/tampering
* “Missing message” UI that doesn’t reveal plaintext, just indicates integrity issue

**Performance:** tiny (hashing).

---

## 7) Voice: secure without “a bunch of latency”

Your current voice (PCM over WS, no E2EE) is the biggest privacy hole.

The lowest-latency, real-world solution is:

### Use WebRTC for media, keep your federation for signaling

* Signaling: your existing WS/federation routes
* Media: WebRTC SRTP (low latency, jitter buffers, NAT traversal)
* For true E2EE beyond SRTP termination concerns: use WebRTC Insertable Streams (where available) or an application-layer frame encryption

This is how modern low-latency secure voice/video is typically done.

If you refuse WebRTC and keep WS streaming:

* You can still E2EE frames with AEAD + sequence numbers,
* but you’ll end up re-implementing jitter buffering + congestion control badly.
So: **WebRTC is the performance-friendly choice.**
82 changes: 82 additions & 0 deletions V0.2a_Status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Blackwire v0.2a Status (as of 2026-02-23)

This file tracks what has been implemented from the v0.2 milestones and what is deferred to v0.2b.

## v0.2a Milestones

### 1) Client message signatures + sender-key pinning
Status: Done

- Added detached signing/verification support in client crypto service.
- `/api/v2/messages/send` now carries signed per-device envelopes.
- Client verifies sender signatures before accept/decrypt.
- TOFU pinning map is persisted by `sender_device_uid`; key change triggers hard integrity warning.

### 2) True multi-device accounts + revoke (kick)
Status: Done

- Server supports multi-device listing, active/revoked status, and revoke endpoint in `/api/v2`.
- Revoke flow invalidates device sessions and enforces immediate cutoff behavior.
- Client send path resolves all active recipient devices and mirrors to own active devices.
- Settings UI now shows device inventory and supports kick/revoke with confirmation.

### 3) Federation trust bound to Tor onion identity
Status: Done (v0.2a scope)

- v2 federation well-known includes binding metadata/signing key.
- Peer onboarding validates signing key against onion-derived identity binding (Tor mode path).
- Existing signed/nonce federation protections are preserved.

### 4) Asymmetric, device-bound JWT sessions (bootstrap -> bind)
Status: Done

- Added v2 bootstrap auth flow (`register/login` -> bootstrap token).
- Added device registration and bind-device exchange for device-bound token issuance.
- Added EdDSA token subsystem (`sub`, `did`, `type`, `iat`, `exp`, `jti`) with refresh rotation.
- v2 auth dependencies enforce active device ownership on protected routes.

### 5) End-to-end delivery integrity chain + integrity UI signaling
Status: Done

- v2 message events store sender chain fields (`sender_prev_hash`, `sender_chain_hash`).
- Client computes/signs canonical message material and validates chain continuity.
- Integrity mismatches (key change/signature/chain gap) are surfaced as warnings.
- UI wiring now includes integrity warning banner + settings integrity status area.

### 6) Parallel `/api/v2` with `/api/v1` compatibility
Status: Done

- Added full `/api/v2` router set and WS endpoint without removing `/api/v1`.
- Added v2 message tables and flow without destructive rewrite of v1 tables.
- v1 compatibility path remains in place.

### 7) Tests for v2 + v1 regression retention
Status: Mostly done (server complete, client pending local execution)

- Added server integration coverage for v2 security core behavior.
- Existing v1 tests are still passing in current run.
- Client tests were expanded (crypto + serialization updates), but full local execution is still blocked in this environment because `cmake` is unavailable.

## What is Left for v0.2b

### A) X3DH + Double Ratchet migration
Status: Not started (deferred by plan)

Planned next:
- Prekey publishing/consumption model.
- Session establishment via X3DH.
- Double Ratchet per device-pair with replay/ordering handling.
- Migration path from sealed-box-only v0.2a envelopes.

### B) WebRTC media migration
Status: Not started (deferred by plan)

Planned next:
- Keep signaling on existing control plane.
- Move voice media off raw WS PCM to WebRTC media path.
- Add media-plane E2EE strategy compatible with federation design.

## Notes

- v0.2a core security milestones are implemented in code and API surface.
- Remaining work to fully close v0.2a is operational validation on a machine with CMake/Qt test toolchain available.
72 changes: 72 additions & 0 deletions V0.2b_Status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Blackwire v0.2b Status

## Completed in this implementation pass

### v0.2b1 (X3DH/Double Ratchet rollout scaffolding + dual-stack contracts)
- Added ratchet/prekey schema migration:
- `server/migrations/versions/20260223_0006_v2_ratchet_core.py`
- New tables: `device_signed_prekeys`, `device_one_time_prekeys`, `ratchet_sessions`, `ratchet_skipped_keys`
- Extended `message_events` with indexed `encryption_mode`
- Added v2 prekey contracts and service:
- `POST /api/v2/keys/prekeys/upload`
- `GET /api/v2/users/resolve-prekeys`
- `GET /api/v2/federation/users/{username}/prekeys`
- Extended v2 device resolution contract:
- Per-device `supported_message_modes` in local and federation device responses
- Extended v2 messaging contract:
- `encryption_mode` accepted and persisted (`sealedbox_v0_2a`, `ratchet_v0_2b1`)
- Ratchet envelope fields supported with typed schema validation: `ratchet_header`, optional `ratchet_init`
- Policy enforcement:
- `BLACKWIRE_ENABLE_RATCHET_V2B1`
- `BLACKWIRE_RATCHET_REQUIRE_FOR_LOCAL`
- `BLACKWIRE_RATCHET_REQUIRE_FOR_FEDERATION`
- Mode-specific metrics counters emitted
- Additional ratchet metrics wired:
- `ratchet.session.established`
- `ratchet.prekey.opk.exhausted`
- Client wiring for dual-stack behavior:
- DTO/API support for prekey upload/resolve and `encryption_mode`
- Send path negotiates ratchet mode by capability + prekey availability, else sealed-box fallback
- Prekey upload on device setup/re-bind
- Full cryptographic implementation of X3DH + Double Ratchet state transitions:
- Real root/send/recv chain key evolution
- Skipped-key material encryption lifecycle
- Post-compromise recovery semantics
- End-to-end ratchet decrypt path replacing sealed-box fallback behavior


### v0.2b2 (WebRTC signaling migration scaffolding)
- Added config gating:
- `BLACKWIRE_ENABLE_WEBRTC_V2B2`
- `BLACKWIRE_WEBRTC_ICE_SERVERS_JSON` startup validation
- `BLACKWIRE_ENABLE_LEGACY_CALL_AUDIO_WS`
- Added v2 WS signaling events:
- `call.webrtc.offer`
- `call.webrtc.answer`
- `call.webrtc.ice`
- Added v2 federation relay endpoints:
- `POST /api/v2/federation/calls/webrtc-offer`
- `POST /api/v2/federation/calls/webrtc-answer`
- `POST /api/v2/federation/calls/webrtc-ice`
- Added call schema fields for forward compatibility:
- `call_schema_version`, `call_mode`, `max_participants`
- Added WebRTC metadata propagation in `call.accepted` payloads:
- `call_schema_version`, `call_mode`, `max_participants`, `ice_servers`
- Client WS and controller wiring:
- New DTO/events/methods for WebRTC signaling
- UI state updates for signaling progress (`reason` changes/diagnostics), including ICE metadata diagnostics
- Real `libwebrtc` media engine integration in Qt client
- Actual SDP/ICE generation, candidate gathering, and RTP media track transport
- TURN/STUN runtime integration and media-failure recovery logic
- Decommissioning WS PCM transport after stabilization window


## Tests added and executed
- Added integration tests:
- `server/tests/integration/test_v2_prekey_upload_and_resolve` (in `test_v2_security_core.py`)
- `server/tests/integration/test_v2_ratchet_send_rejected_when_feature_disabled` (in `test_v2_security_core.py`)
- `server/tests/integration/test_v2_webrtc_signaling.py`
- Executed and passing:
- `server/tests/integration/test_v2_security_core.py`
- `server/tests/integration/test_v2_webrtc_signaling.py`
- Selected legacy voice tests passed (`test_offer_accept_audio_end`, `test_busy_and_invalid_audio_errors`)
Loading
Loading