docs: correct inaccurate privacy and metadata claims (#1485)

* docs: correct inaccurate privacy and metadata claims

Several documented guarantees did not match the implementation. These
matter more than ordinary doc drift: someone deciding whether to carry
this phone to a protest reads these sentences as the threat model.

- Peer IDs were described as "short ephemeral IDs derived per session"
  that "rotate periodically" and "prevent tracking". They are the first
  8 bytes of the Noise static key fingerprint, stable across sessions
  and reboots, and replaced only by a panic wipe. Corrected in the
  whitepaper (§3, §8), IdentityModels, and BitchatProtocol, whose
  header notes claimed "no persistent identifiers in protocol headers"
  while every header carries exactly one.
- "No plaintext message content is ever written to disk" was false for
  accepted media, which is stored unsealed under the platform's
  data-protection class. Narrowed to what actually holds.
- Padding was described as applying to all packets but fragments. Only
  noiseEncrypted and noiseHandshake frames are padded; the pad bytes
  equal the pad length rather than being random; and because that
  length must fit one byte, a frame needing over 255 bytes of padding
  is emitted unpadded. Documented in the whitepaper (§4.1) and
  MessagePadding.
- The gossip archive window is 6 hours in production, not the
  15 minutes claimed in PRIVACY_POLICY.md and the privacy assessment.
  The 15-minute figure is the struct default that BLEService overrides.
- The privacy assessment credited iOS BLE address randomization without
  noting that stable app-layer identifiers defeat it.

The whitepaper's future-work list now names the changes these
corrections imply: rotating on-air identity, padding for non-Noise
types, and making the announce neighbor list optional.

No behavior change; comments and documentation only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs: correct the same claims in the README

The README repeats two of the claims corrected elsewhere in this PR, and
it is the document people actually read before deciding to trust the app.

- "no persistent identifiers" is the inverse of what the mesh does; it
  now points at the whitepaper's identity and metadata sections.
- "end-to-end encryption with forward secrecy" holds for live Noise
  sessions but not for sealed store-and-forward mail, which the
  whitepaper already flags as its main cryptographic trade-off.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
jack
2026-07-26 19:02:26 +02:00
committed by GitHub
co-authored by jack Claude Opus 5
parent 934b2cd2d3
commit 229a41557e
7 changed files with 65 additions and 31 deletions
+29 -17
View File
@@ -14,18 +14,22 @@
///
/// ## Overview
/// BitChat's identity system separates concerns across three distinct layers:
/// 1. **Ephemeral Identity**: Short-lived, rotatable peer IDs for privacy
/// 1. **Network Identity**: the 8-byte peer ID seen on air
/// 2. **Cryptographic Identity**: Long-term Noise static keys for security
/// 3. **Social Identity**: User-assigned names and trust relationships
/// 3. **Social Identity**: assigned names and trust relationships
///
/// This separation allows users to maintain stable cryptographic identities
/// while frequently rotating their network identifiers for privacy.
/// The layers are separate concerns, but they are not independent: the network
/// identity is *derived* from the cryptographic one, so it does not provide
/// unlinkability. Rotating peer IDs would be a change to this model, not a
/// description of it see the note below.
///
/// ## Three-Layer Architecture
///
/// ### Layer 1: Ephemeral Identity
/// - Random 8-byte peer IDs that rotate periodically
/// - Provides network-level privacy and prevents tracking
/// ### Layer 1: Network Identity
/// - 8-byte peer ID = first 8 bytes of the Noise static key fingerprint
/// - **Not ephemeral and not rotating.** It is stable across sessions and
/// reboots, and changes only when the underlying identity is replaced by a
/// panic wipe. A passive observer can use it to track a device.
/// - Changes don't affect cryptographic relationships
/// - Includes handshake state tracking
///
@@ -33,7 +37,7 @@
/// - Based on Noise Protocol static key pairs
/// - Fingerprint derived from SHA256 of public key
/// - Enables end-to-end encryption and authentication
/// - Persists across peer ID rotations
/// - The root of the peer ID above, and never rotated on a schedule
///
/// ### Layer 3: Social Identity
/// - User-assigned names (petnames) for contacts
@@ -44,10 +48,13 @@
/// ## Privacy Design
/// The model is designed with privacy-first principles:
/// - No mandatory persistent storage
/// - Optional identity caching with user consent
/// - Ephemeral IDs prevent long-term tracking
/// - Optional identity caching with explicit consent
/// - Social mappings stored locally only
///
/// It does **not** currently prevent long-term tracking by a passive radio
/// observer: the peer ID is stable (Layer 1) and signed announcements carry the
/// static keys and nickname in cleartext.
///
/// ## Trust Model
/// Four levels of trust:
/// 1. **Unknown**: New or unverified peers
@@ -56,17 +63,17 @@
/// 4. **Verified**: Cryptographic verification completed
///
/// ## Identity Resolution
/// When a peer rotates their ephemeral ID:
/// When a peer's ID changes (a panic wipe on their side, or a future rotation):
/// 1. Cryptographic handshake reveals their fingerprint
/// 2. System looks up social identity by fingerprint
/// 3. UI seamlessly maintains user relationships
/// 3. UI seamlessly maintains existing relationships
/// 4. Historical messages remain properly attributed
///
/// ## Conflict Resolution
/// Handles edge cases like:
/// - Multiple peers claiming same nickname
/// - Nickname changes and conflicts
/// - Identity rotation during active chats
/// - Identity replacement during active chats
/// - Network partitions and rejoins
///
/// ## Usage Example
@@ -85,8 +92,12 @@ import BitFoundation
// MARK: - Three-Layer Identity Model
/// Represents the ephemeral layer of identity - short-lived peer IDs that provide network privacy.
/// These IDs rotate periodically to prevent tracking while maintaining cryptographic relationships.
/// Represents the network layer of identity the peer ID seen on air, plus the
/// handshake state tracked against it.
///
/// Named "ephemeral" for historical reasons; the peer ID is in fact stable,
/// being derived from the Noise static key fingerprint. It does not rotate and
/// does not prevent tracking.
struct EphemeralIdentity {
var handshakeState: HandshakeState
}
@@ -99,8 +110,9 @@ enum HandshakeState {
}
/// Represents the cryptographic layer of identity - the stable Noise Protocol static key pair.
/// This identity persists across ephemeral ID rotations and enables secure communication.
/// The fingerprint serves as the permanent identifier for a peer's cryptographic identity.
/// This identity outlives any change to a peer's network ID and enables secure communication.
/// The fingerprint serves as the permanent identifier for a peer's cryptographic identity, and
/// its first 8 bytes are the peer ID broadcast on the mesh.
struct CryptographicIdentity: Codable {
let fingerprint: String // SHA256 of public key
let publicKey: Data // Noise static public key
+6 -2
View File
@@ -38,11 +38,15 @@
/// 7. **Decoding**: Binary data parsed back to message objects
///
/// ## Security Considerations
/// - Message padding (to 256/512/1024/2048-byte blocks) obscures actual content length
/// - Noise frames are padded (to 256/512/1024/2048-byte blocks) to obscure
/// content length; other packet types are not padded, so their payload
/// length is observable
/// - Randomized relay jitter reduces the traffic-analysis signal; there is no
/// cover traffic or per-message timing obfuscation
/// - Integration with Noise Protocol for E2E encryption
/// - No persistent identifiers in protocol headers
/// - The 8-byte sender ID in every header IS a persistent identifier: it is
/// derived from the long-lived Noise static key and rotates only on a panic
/// wipe. Treat headers as linkable across sessions.
///
/// ## Message Types
/// - **Announce/Leave**: Peer presence notifications