import Foundation import Security enum KeychainHelper { static func save(_ secret: String, account: String, service: String = "RemminaMac") -> Bool { guard let data = secret.data(using: .utf8) else { return false } delete(account: account, service: service) let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account, kSecValueData as String: data, kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked ] return SecItemAdd(query as CFDictionary, nil) == errSecSuccess } static func load(account: String, service: String = "RemminaMac") -> String? { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var item: CFTypeRef? guard SecItemCopyMatching(query as CFDictionary, &item) == errSecSuccess, let data = item as? Data else { return nil } return String(data: data, encoding: .utf8) } static func delete(account: String, service: String = "RemminaMac") { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account ] SecItemDelete(query as CFDictionary) } }