feat: add HPKE e2e encryption on relay for Bonjour-paired peers#958
feat: add HPKE e2e encryption on relay for Bonjour-paired peers#958ritave wants to merge 3 commits into
Conversation
Fixed: 1. HPKEKeyStore.swift — public-key caching. publicKeyBytes and publicKeyEncoded were re-deriving from the private key on every call, which BonjourAdvertiser hits per agent on every TXT republish. Now cached alongside _privateKey, with cache invalidation on warmUp and reset. 2. HPKEKeyStore.swift — zeroize derived bytes in warmUp. The 32-byte derived key is now wiped from the local stack after writing to keychain, matching the security hygiene MasterKey.generate() already enforces on its own bytes. 3. HPKEKeyStore.swift — fixed inverted comment. Renamed privateKeyUnlocked → privateKeyLocked (caller holds lock) and corrected the docstring. 4. HPKEEncryption.swift — single-shot sender. _sender is now Optional, consumed (set to nil) on first sealRequestBody call. A second call throws sealFailed instead of silently producing counter-1 ciphertext the server can't open. 5. HPKEEncryption.swift — dropped unused HPKEClientContext.suite field. It mirrored the singleton constant and wasn't read anywhere. 6. HTTPHandler.swift — skip body copy on plaintext requests. The encryption block now reads the body buffer only inside the contains(name:) branch, so plaintext traffic doesn't pay for an extra Data allocation per request. 7. HTTPHandler.swift — defensive context clear in .end cleanup. stateRef.value.encryptionContext = nil after dispatch, matching the existing requestHead/requestBodyBuffer cleanup. Stops a prior request's context from leaking forward if HTTP keep-alive is ever enabled (today's Connection: close keeps it 1:1, but the cleanup is one line of insurance). 8. RemoteProviderService.swift — fixed O(n²) buffer scan in makeDecryptingChunkStream. Tracks a searchStart index that advances past already-scanned bytes (with a 1-byte overlap so a separator straddling the boundary still matches). Drops worst-case from O(n²) to O(n) over a long stream. Skipped (deliberately): - Removing hpkeSuite from the model — agent flagged it as dead state, but it's the wire-format gate for future suite negotiation, not pure dead code. - Extracting a shared HMAC-SHA512 KDF helper across AgentKey/PairingKey/HPKEKeyStore — out of scope; would touch unrelated identity code. - Protocol-ifying var encryption across the four ResponseWriter classes — small churn for limited win; the current shared emitEvent free function is clear. - Struct-based encryption-header parser — only one suite exists today. - Test isolation refactor (HPKEKeyStore(testMode:)) — current .serialized works fine for 7 fast tests.
1b00c35 to
d63bdca
Compare
|
Status note from the PR cleanup pass: the latest visible checks are green, but this PR is still draft and currently marked |
|
@tpae separate CI note: This PR's failure is not the provider/model-picker race affecting the newer red PRs. Its Recommended next step: keep this draft blocked until it is rebased onto current Why: this PR touches relay encryption/identity-adjacent behavior, so we should avoid reviewing or merging it while the build cannot prove the branch even compiles cleanly. |
Summary
Explain the motivation and the changes. Link issues (e.g., Closes #123).
Changes
Test Plan
Steps to verify locally (commands, screenshots, recordings). Include model used.
Screenshots
If UI updated, add before/after.
Checklist
CONTRIBUTING.md