Files
bitchat/BRING_THE_NOISE.md
T

218 lines
5.9 KiB
Markdown

# 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:
```swift
final class NoiseEncryptionService {
private let staticIdentityKey: Curve25519.KeyAgreement.PrivateKey
private let sessionManager: NoiseSessionManager
private let channelEncryption = NoiseChannelEncryption()
}
```
#### NoiseSession
Individual session state for each peer:
```swift
final 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:
```swift
final class NoiseSessionManager {
private var sessions: [String: NoiseSession] = [:]
private let sessionsQueue = DispatchQueue(label: "noise.sessions", attributes: .concurrent)
}
```
### Handshake Flow
1. **Initiator sends ephemeral key**
```swift
let ephemeralKey = Curve25519.KeyAgreement.PrivateKey()
let message = ephemeralKey.publicKey.rawRepresentation
```
2. **Responder sends ephemeral + encrypted static**
```swift
// Generate ephemeral, perform DH, encrypt static key
let encryptedStatic = encrypt(staticKey, using: sharedSecret)
```
3. **Initiator sends encrypted static**
```swift
// Complete handshake, derive session keys
let (sendKey, recvKey) = deriveSessionKeys(transcript)
```
### Session Management
Sessions are managed with automatic cleanup and rekey support:
```swift
// 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:
```swift
// 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:
```swift
// Encrypt message
let encrypted = try noiseService.encrypt(messageData, for: peerID)
// Decrypt message
let decrypted = try noiseService.decrypt(encryptedData, from: 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
### Cryptographic Primitives
- **DH**: X25519 (Curve25519)
- **Cipher**: ChaChaPoly (AEAD)
- **Hash**: SHA-256
- **KDF**: HKDF-SHA256
### Error Handling
```swift
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
## Protocol Version Negotiation
BitChat implements protocol version negotiation to ensure compatibility between different client versions:
### Version Negotiation Flow
1. **Version Hello**: Upon connection, peers exchange supported protocol versions
2. **Version Agreement**: Peers agree on the highest common version
3. **Graceful Fallback**: Legacy peers without version negotiation assume protocol v1
### Message Types
```swift
case versionHello = 0x20 // Announce supported versions
case versionAck = 0x21 // Acknowledge and agree on version
```
### Backward Compatibility
- Peers that don't send version negotiation messages are assumed to support v1
- Future protocol versions can be added to `ProtocolVersion.supportedVersions`
- Incompatible peers receive a rejection message and disconnect gracefully
## 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.