import Foundation enum DatabaseEncryptionKeyError: Error { case keyNotAvailable } final class DatabaseEncryptionKeyManager { static let shared = DatabaseEncryptionKeyManager() private let keychainService: KeychainService private let serviceName = "yobble.database.encryption" private let accountName = "sqlcipher_key" /// Hardcoded dev key used until the user saves their own password-derived key. private let fallbackKey: String init( keychainService: KeychainService = .shared, fallbackKey: String = AppConfig.DEFAULT_DATABASE_ENCRYPTION_KEY ) { self.keychainService = keychainService self.fallbackKey = fallbackKey } func currentKey() throws -> String { if let key = keychainService.get(forKey: accountName, service: serviceName), !key.isEmpty { return key } guard !fallbackKey.isEmpty else { throw DatabaseEncryptionKeyError.keyNotAvailable } return fallbackKey } func persistKey(_ key: String) { keychainService.save(key, forKey: accountName, service: serviceName) } func clearPersistedKey() { keychainService.delete(forKey: accountName, service: serviceName) } func hasPersistedKey() -> Bool { keychainService.get(forKey: accountName, service: serviceName) != nil } }