Refactor: Testable Keychain and Identity Manager (#584)

* Make static functions instance functions to be testable

* Injectable KeychainManager + Mock + updated tests

* Remove `pendingActions` from identity manager (dead code)

* Remove `getHandshakeState` from identity manager (dead code)

* Remove `getAllSocialIdentities` from identity manager (dead code)

* Remove `getCryptographicIdentity` from identity manager (dead code)

* Remove `resolveIdentity` from identity manager (dead code)

* Identity Manager: minor clean up

* Put Identity Manager behind a protocol

* Remove Keychain and Identity Manager singletons

* Tests: include MockKeychain/MockIdentityManager in project; init identityManager in CommandProcessorTests

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
Islam
2025-09-12 14:37:34 +02:00
committed by GitHub
co-authored by jack
parent bb3d99bdca
commit 920dc31795
22 changed files with 445 additions and 234 deletions
+14 -7
View File
@@ -9,16 +9,23 @@
import Foundation
import Security
final class KeychainManager {
static let shared = KeychainManager()
protocol KeychainManagerProtocol {
func saveIdentityKey(_ keyData: Data, forKey key: String) -> Bool
func getIdentityKey(forKey key: String) -> Data?
func deleteIdentityKey(forKey key: String) -> Bool
func deleteAllKeychainData() -> Bool
func secureClear(_ data: inout Data)
func secureClear(_ string: inout String)
func verifyIdentityKeyExists() -> Bool
}
final class KeychainManager: KeychainManagerProtocol {
// Use consistent service name for all keychain items
private let service = "chat.bitchat"
private let appGroup = "group.chat.bitchat"
private init() {}
private func isSandboxed() -> Bool {
#if os(macOS)
// More robust sandbox detection using multiple methods
@@ -310,7 +317,7 @@ final class KeychainManager {
// MARK: - Security Utilities
/// Securely clear sensitive data from memory
static func secureClear(_ data: inout Data) {
func secureClear(_ data: inout Data) {
_ = data.withUnsafeMutableBytes { bytes in
// Use volatile memset to prevent compiler optimization
memset_s(bytes.baseAddress, bytes.count, 0, bytes.count)
@@ -319,7 +326,7 @@ final class KeychainManager {
}
/// Securely clear sensitive string from memory
static func secureClear(_ string: inout String) {
func secureClear(_ string: inout String) {
// Convert to mutable data and clear
if var data = string.data(using: .utf8) {
secureClear(&data)