mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 22:45:19 +00:00
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.
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
# 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
|
||||
class NoiseEncryptionService {
|
||||
private let staticIdentityKey: Curve25519.KeyAgreement.PrivateKey
|
||||
private let sessionManager: NoiseSessionManager
|
||||
private let channelEncryption = NoiseChannelEncryption()
|
||||
}
|
||||
```
|
||||
|
||||
#### NoiseSession
|
||||
Individual session state for each peer:
|
||||
```swift
|
||||
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
|
||||
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)
|
||||
```
|
||||
|
||||
### Channel Encryption
|
||||
|
||||
Password-protected channels use Noise for key distribution:
|
||||
|
||||
```swift
|
||||
// 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
|
||||
```swift
|
||||
// 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
|
||||
```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
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user