import Foundation import Security enum KeychainStore { private static var service: String { "am.sure.native" } static func saveAPIKey(_ value: String) throws { guard let data = value.data(using: .utf8) else { return } let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: "api-key" ] SecItemDelete(query as CFDictionary) var attributes = query attributes[kSecValueData as String] = data attributes[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly let status = SecItemAdd(attributes as CFDictionary, nil) guard status == errSecSuccess else { throw KeychainError(status: status) } } static func readAPIKey() -> String? { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: "api-key", kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var result: AnyObject? guard SecItemCopyMatching(query as CFDictionary, &result) == errSecSuccess, let data = result as? Data else { return nil } return String(data: data, encoding: .utf8) } static func deleteAPIKey() { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: "api-key" ] SecItemDelete(query as CFDictionary) } } struct KeychainError: LocalizedError { var status: OSStatus var errorDescription: String? { "Could not securely save the API key (\(status))." } }