Files
bitchat/bitchat/Views/NoiseTestingView.swift
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

129 lines
5.0 KiB
Swift

//
// NoiseTestingView.swift
// bitchat
//
// This is free and unencumbered software released into the public domain.
// For more information, see <https://unlicense.org>
//
import SwiftUI
#if DEBUG
struct NoiseTestingView: View {
@ObservedObject var viewModel: ChatViewModel
@Environment(\.colorScheme) var colorScheme
@State private var testChecklist = NoiseTestingHelper.shared.getTestChecklist()
private var textColor: Color {
colorScheme == .dark ? Color.green : Color(red: 0, green: 0.5, blue: 0)
}
private var backgroundColor: Color {
colorScheme == .dark ? Color.black : Color.white
}
var body: some View {
VStack(alignment: .leading, spacing: 16) {
// Header
Text("NOISE PROTOCOL TEST HELPER")
.font(.system(size: 16, weight: .bold, design: .monospaced))
.foregroundColor(textColor)
.padding(.bottom)
// Status Overview
VStack(alignment: .leading, spacing: 8) {
Text("CURRENT STATUS:")
.font(.system(size: 12, weight: .bold, design: .monospaced))
.foregroundColor(textColor.opacity(0.7))
ForEach(viewModel.connectedPeers, id: \.self) { peerID in
let nickname = viewModel.meshService.getPeerNicknames()[peerID] ?? "Unknown"
let status = viewModel.getEncryptionStatus(for: peerID)
HStack {
Image(systemName: status.icon)
.font(.system(size: 12))
.foregroundColor(status == .noiseVerified ? Color.green :
status == .noiseSecured ? textColor :
Color.red)
Text("\(nickname): \(status.description)")
.font(.system(size: 12, design: .monospaced))
.foregroundColor(textColor)
Spacer()
}
}
if viewModel.connectedPeers.isEmpty {
Text("No peers connected")
.font(.system(size: 12, design: .monospaced))
.foregroundColor(Color.gray)
}
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(8)
// Test Checklist
ScrollView {
Text(testChecklist)
.font(.system(size: 11, design: .monospaced))
.foregroundColor(textColor)
.textSelection(.enabled)
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(8)
// Debug Actions
HStack(spacing: 16) {
Button("Force Handshake") {
// Trigger handshake with all peers by sending a broadcast announce
// This will cause all peers to re-exchange keys
viewModel.meshService.sendBroadcastAnnounce()
}
.foregroundColor(textColor)
Button("Clear Sessions") {
// Clear all Noise sessions for testing
let noiseService = viewModel.meshService.getNoiseService()
for peerID in viewModel.connectedPeers {
noiseService.removePeer(peerID)
}
viewModel.peerEncryptionStatus.removeAll()
}
.foregroundColor(Color.orange)
Button("Copy Logs") {
// Copy test results to clipboard
var logs = "NOISE PROTOCOL TEST RESULTS\n"
logs += "===========================\n\n"
logs += "Timestamp: \(Date())\n"
logs += "Connected Peers: \(viewModel.connectedPeers.count)\n\n"
for peerID in viewModel.connectedPeers {
let nickname = viewModel.meshService.getPeerNicknames()[peerID] ?? "Unknown"
let status = viewModel.getEncryptionStatus(for: peerID)
logs += "\(nickname) (\(peerID)): \(status.description)\n"
}
#if os(iOS)
UIPasteboard.general.string = logs
#else
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(logs, forType: .string)
#endif
}
.foregroundColor(textColor)
Spacer()
}
}
.padding()
.frame(width: 500, height: 600)
.background(backgroundColor)
}
}
#endif