Spaces:
Paused
Paused
| import Foundation | |
| import Security | |
| enum KeychainStore { | |
| static func loadString(service: String, account: String) -> 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? | |
| let status = SecItemCopyMatching(query as CFDictionary, &item) | |
| guard status == errSecSuccess, let data = item as? Data else { return nil } | |
| return String(data: data, encoding: .utf8) | |
| } | |
| static func saveString(_ value: String, service: String, account: String) -> Bool { | |
| let data = Data(value.utf8) | |
| let query: [String: Any] = [ | |
| kSecClass as String: kSecClassGenericPassword, | |
| kSecAttrService as String: service, | |
| kSecAttrAccount as String: account, | |
| ] | |
| let update: [String: Any] = [kSecValueData as String: data] | |
| let status = SecItemUpdate(query as CFDictionary, update as CFDictionary) | |
| if status == errSecSuccess { return true } | |
| if status != errSecItemNotFound { return false } | |
| var insert = query | |
| insert[kSecValueData as String] = data | |
| insert[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly | |
| return SecItemAdd(insert as CFDictionary, nil) == errSecSuccess | |
| } | |
| static func delete(service: String, account: String) -> Bool { | |
| let query: [String: Any] = [ | |
| kSecClass as String: kSecClassGenericPassword, | |
| kSecAttrService as String: service, | |
| kSecAttrAccount as String: account, | |
| ] | |
| let status = SecItemDelete(query as CFDictionary) | |
| return status == errSecSuccess || status == errSecItemNotFound | |
| } | |
| } | |