// // KeychainHelper.swift // StikDebug // // Created by Stephen on 7/29/25. // import Security final class KeychainHelper { static let shared = KeychainHelper() private init() {} func save(password: String, forKey key: String) { let pwData = password.data(using: .utf8)! let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: key] SecItemDelete(query as CFDictionary) let add: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: key, kSecValueData as String: pwData, kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock] SecItemAdd(add as CFDictionary, nil) } func readPassword(forKey key: String) -> String? { let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: key, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne] var out: CFTypeRef? let status = SecItemCopyMatching(query as CFDictionary, &out) guard status == errSecSuccess, let data = out as? Data else { return nil } return String(data: data, encoding: .utf8) } func deletePassword(forKey key: String) { let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: key] SecItemDelete(query as CFDictionary) } }