A REQUEST_SYNC reply can carry a message from a peer that has left, on
LEAVE or after three minutes of silence. Normally the neighbor re-serves
that peer's announcement first, which restores the signing key. When the
key is not restored, the message arrives with no key on file and the
signature check rejects it. That happens in two cases. An iOS neighbor
that relaunched serves messages restored from disk, and that archive
holds no announcements. An Android neighbor that missed the LEAVE keeps
serving the peer for about three minutes while the receiving device
rejects the re-served announcement as a duplicate. iOS keeps a message
from a sender that has left when it has verified that sender before, by
falling back to its persisted identity. Android persists the signing key
for every peer that completed the authenticated peer-state exchange, and
the message path did not read it. This addresses the first bullet of
#622.
The signature check falls back to the persisted signing key when the
live registry has none, found by peer ID directly since a peer ID is the
prefix of its own fingerprint. The broadcast handler delivers a message
from a sender that has left under the cached nickname or the peer ID. A
message from a sender that has left is not archived, and nothing the
LEAVE purge removed re-enters the archive. Messages from present peers
and the receiving device's own broadcasts are archived as before. A live
key is always preferred, a sender with no key on file is rejected as
before, and a registry entry with an unverified nickname is dropped as
before. Receive-side only.
Seventeen tests across the security manager, the message handler, the
coordinator, the secure store and the sync archive.
C1 from security review: SymmetricState/HandshakeState logged raw X25519
shared secrets, chaining keys, and handshake hashes in hex to logcat on
every handshake, in release builds. A logcat transcript of a handshake
allowed full session decryption. Both classes no longer log at all.
Also reduces excessive logging across the app (~50% fewer log calls in
the noisiest files):
- NoiseSession emits one line per completed handshake; per-message
encrypt/decrypt and per-handshake-step debug logs removed
- Removes all content/key logging: decrypted DM content, file names,
payload hex dumps, pubkeys, event IDs, lat/lon, peer IPs, arti log
forwarding
- Collapses multi-line banner/emoji log sequences into single factual
lifecycle lines (connect/disconnect, relay/Tor state transitions)
- Keeps security-relevant warnings (signature failures, replay
detection, key mismatches, panic wipe) in compact form
No logic changes. Includes the full security review report in
docs/security-review-jul-27.md.
* Bind Noise sessions to claimed peer identities
* Make Wi-Fi peer rebinding atomic
* Migrate private media without silent downgrades (#728)
* Migrate private media without silent downgrades
* Accept prerelease private media payloads
* Authenticate private media capability per Noise session
* updates
---------
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: jack <jack@deck.local>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
* Authenticate BLE links before peer binding (#749)
* Authenticate BLE links before peer binding
* Fix BLE link authentication races
---------
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
* Use canonical Maven repository for Robolectric
---------
Co-authored-by: jack <jack@deck.local>
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
Co-authored-by: a1denvalu3 <43107113+a1denvalu3@users.noreply.github.com>