mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 08:45:19 +00:00
Add proper error classification to distinguish expected states (item not found) from critical failures (access denied, storage full) and recoverable errors (device locked, auth failed). Changes: - Add KeychainReadResult and KeychainSaveResult enums with error types - Add getIdentityKeyWithResult/saveIdentityKeyWithResult protocol methods - Implement retry logic with exponential backoff for transient errors - Add consistent SecureLogger logging for all keychain operations - Update NoiseEncryptionService identity loading to handle errors gracefully - Update MockKeychain and TrackingMockKeychain with error simulation - Add comprehensive KeychainErrorHandlingTests (18 new tests) Security: Applications can now properly detect and respond to critical keychain failures, improving resilience during device lock states and providing actionable diagnostics for access issues. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
74 lines
1.9 KiB
Swift
74 lines
1.9 KiB
Swift
//
|
|
// PreviewKeychainManager.swift
|
|
// bitchat
|
|
//
|
|
// This is free and unencumbered software released into the public domain.
|
|
// For more information, see <https://unlicense.org>
|
|
//
|
|
|
|
import Foundation
|
|
|
|
final class PreviewKeychainManager: KeychainManagerProtocol {
|
|
private var storage: [String: Data] = [:]
|
|
private var serviceStorage: [String: [String: Data]] = [:]
|
|
init() {}
|
|
|
|
func saveIdentityKey(_ keyData: Data, forKey key: String) -> Bool {
|
|
storage[key] = keyData
|
|
return true
|
|
}
|
|
|
|
func getIdentityKey(forKey key: String) -> Data? {
|
|
storage[key]
|
|
}
|
|
|
|
func deleteIdentityKey(forKey key: String) -> Bool {
|
|
storage.removeValue(forKey: key)
|
|
return true
|
|
}
|
|
|
|
func deleteAllKeychainData() -> Bool {
|
|
storage.removeAll()
|
|
serviceStorage.removeAll()
|
|
return true
|
|
}
|
|
|
|
func secureClear(_ data: inout Data) {}
|
|
|
|
func secureClear(_ string: inout String) {}
|
|
|
|
func verifyIdentityKeyExists() -> Bool {
|
|
storage["identity_noiseStaticKey"] != nil
|
|
}
|
|
|
|
// BCH-01-009: New methods with proper error classification
|
|
func getIdentityKeyWithResult(forKey key: String) -> KeychainReadResult {
|
|
if let data = storage[key] {
|
|
return .success(data)
|
|
}
|
|
return .itemNotFound
|
|
}
|
|
|
|
func saveIdentityKeyWithResult(_ keyData: Data, forKey key: String) -> KeychainSaveResult {
|
|
storage[key] = keyData
|
|
return .success
|
|
}
|
|
|
|
// MARK: - Generic Data Storage (consolidated from KeychainHelper)
|
|
|
|
func save(key: String, data: Data, service: String, accessible: CFString?) {
|
|
if serviceStorage[service] == nil {
|
|
serviceStorage[service] = [:]
|
|
}
|
|
serviceStorage[service]?[key] = data
|
|
}
|
|
|
|
func load(key: String, service: String) -> Data? {
|
|
serviceStorage[service]?[key]
|
|
}
|
|
|
|
func delete(key: String, service: String) {
|
|
serviceStorage[service]?.removeValue(forKey: key)
|
|
}
|
|
}
|