Files
bitchat/BRING_THE_NOISE.md
T
jack 3070a4d307 Implement Noise Protocol Framework and peer ID rotation for enhanced security and privacy
This major update replaces the basic encryption with the Noise Protocol Framework
and adds ephemeral peer ID rotation for enhanced privacy.

Key Changes:

Security Infrastructure:
- Implemented Noise Protocol Framework (XX handshake pattern)
- End-to-end encryption with forward secrecy and identity hiding
- Session management with automatic rekey support
- Channel encryption with password-derived keys

Privacy Enhancements:
- Ephemeral peer ID rotation (5-15 minute random intervals)
- Persistent identity through public key fingerprints
- Favorites and verification persist across ID rotations
- Block list based on fingerprints, not ephemeral IDs

Core Components Added:
- NoiseEncryptionService: Main encryption service
- NoiseSession: Individual peer session management
- NoiseChannelEncryption: Password-protected channel support
- SecureIdentityStateManager: Persistent identity storage
- FingerprintView: Visual fingerprint verification UI

Bug Fixes:
- Fixed handshake storm with tie-breaker mechanism
- Fixed missing connect messages during peer rotation
- Fixed delivery ACK compression issues
- Fixed race conditions in message queue
- Fixed nickname resolution for rotated peer IDs

Testing:
- Comprehensive test suite for Noise implementation
- Security validator tests
- Channel encryption tests
- Identity persistence tests
- Rate limiter tests

Documentation:
- BRING_THE_NOISE.md: Technical implementation details
- Updated WHITEPAPER.md: Simplified and focused on core innovations
- Removed temporary debug documentation

The implementation maintains backward compatibility while significantly
improving security and privacy. All existing features (channels, private
messages, favorites, blocking) work seamlessly with the new system.
2025-07-15 13:15:31 +02:00

5.5 KiB

Bringing the Noise: Secure Communication in BitChat

Overview

BitChat implements the Noise Protocol Framework for end-to-end encryption, providing forward secrecy, identity hiding, and cryptographic authentication. This document details our Swift implementation and its integration with BitChat's decentralized mesh network.

The Noise Protocol Framework

Why Noise?

The Noise Protocol Framework offers:

  • Forward Secrecy: Past messages remain secure even if keys are compromised
  • Identity Hiding: Peer identities are encrypted during handshake
  • Simplicity: Clean, auditable protocol with minimal complexity
  • Performance: Efficient for resource-constrained mobile devices
  • Flexibility: Supports various handshake patterns

The XX Pattern

BitChat uses the Noise XX pattern:

XX:
  -> e
  <- e, ee, s, es
  -> s, se

This three-message pattern provides:

  • Mutual authentication
  • Identity encryption (identities revealed only after initial key exchange)
  • Resistance to key-compromise impersonation

Implementation Architecture

Core Components

NoiseEncryptionService

The main service managing all Noise operations:

class NoiseEncryptionService {
    private let staticIdentityKey: Curve25519.KeyAgreement.PrivateKey
    private let sessionManager: NoiseSessionManager
    private let channelEncryption = NoiseChannelEncryption()
}

NoiseSession

Individual session state for each peer:

class NoiseSession {
    private var handshakeState: NoiseHandshakeState?
    private var sendCipher: NoiseCipherState?
    private var receiveCipher: NoiseCipherState?
    private let remoteStaticKey: Curve25519.KeyAgreement.PublicKey?
}

NoiseSessionManager

Thread-safe session management:

class NoiseSessionManager {
    private var sessions: [String: NoiseSession] = [:]
    private let sessionsQueue = DispatchQueue(label: "noise.sessions", attributes: .concurrent)
}

Handshake Flow

  1. Initiator sends ephemeral key

    let ephemeralKey = Curve25519.KeyAgreement.PrivateKey()
    let message = ephemeralKey.publicKey.rawRepresentation
    
  2. Responder sends ephemeral + encrypted static

    // Generate ephemeral, perform DH, encrypt static key
    let encryptedStatic = encrypt(staticKey, using: sharedSecret)
    
  3. Initiator sends encrypted static

    // Complete handshake, derive session keys
    let (sendKey, recvKey) = deriveSessionKeys(transcript)
    

Session Management

Sessions are managed with automatic cleanup and rekey support:

// Session lookup by peer ID
func getSession(for peerID: String) -> NoiseSession?

// Automatic session removal on disconnect
func removeSession(for peerID: String)

// Rekey detection
func getSessionsNeedingRekey() -> [(String, Bool)]

Integration with BitChat

Peer ID Rotation

Noise sessions persist across peer ID rotations through fingerprint mapping:

// Identity announcement after handshake
struct NoiseIdentityAnnouncement {
    let peerID: String
    let publicKey: Data
    let nickname: String
    let previousPeerID: String?
    let signature: Data
}

Message Encryption

All messages are encrypted using established Noise sessions:

// Encrypt message
let encrypted = try noiseService.encrypt(messageData, for: peerID)

// Decrypt message  
let decrypted = try noiseService.decrypt(encryptedData, from: peerID)

Channel Encryption

Password-protected channels use Noise for key distribution:

// Share channel key securely
let keyPacket = createChannelKeyPacket(password: password, channel: channel)
let encrypted = try encrypt(keyPacket, for: peerID)

Security Properties

Forward Secrecy

  • Ephemeral keys are generated for each handshake
  • Past sessions cannot be decrypted with current keys
  • Automatic rekey after 1 hour or 10,000 messages

Authentication

  • Static keys provide long-term identity
  • Handshake ensures mutual authentication
  • MAC tags prevent message tampering

Privacy

  • Peer identities encrypted during handshake
  • Metadata minimization through padding
  • No persistent session identifiers

Implementation Details

Key Derivation

// HKDF for key derivation
func hkdf(salt: Data, ikm: Data, info: Data, length: Int) -> Data

// Derive channel keys with PBKDF2
func deriveChannelKey(password: String, salt: Data) -> SymmetricKey

Cryptographic Primitives

  • DH: X25519 (Curve25519)
  • Cipher: ChaChaPoly (AEAD)
  • Hash: SHA-256
  • KDF: HKDF-SHA256

Error Handling

enum NoiseError: Error {
    case handshakeFailed
    case invalidMessage
    case sessionNotEstablished
    case decryptionFailed
}

Performance Optimizations

Connection Pooling

  • Reuse established sessions
  • Lazy handshake initiation
  • Session caching with TTL

Message Batching

  • Combine small messages
  • Reduce encryption overhead
  • Optimize for BLE MTU

Memory Management

  • Bounded session cache
  • Automatic cleanup of stale sessions
  • Efficient key rotation

Future Enhancements

Post-Quantum Readiness

  • Hybrid handshake patterns
  • Kyber integration plans
  • Graceful algorithm migration

Advanced Features

  • Multi-device support
  • Session backup/restore
  • Group messaging primitives

Conclusion

BitChat's Noise implementation provides encryption while maintaining the simplicity and performance required for a peer-to-peer messaging application. The protocol's elegant design ensures that people's communications remain private, authenticated, and forward-secure without sacrificing usability.