// // KeychainAccessTests.swift // KeychainAccessTests // // Created by kishikawa katsumi on 2014/12/24. // Copyright (c) 2014 kishikawa katsumi. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import Foundation import XCTest import KeychainAccess class KeychainAccessTests: XCTestCase { override func setUp() { super.setUp() do { try Keychain(service: "Twitter", accessGroup: "27AEDK3C9F.shared").removeAll() } catch {} do { try Keychain(service: "Twitter").removeAll() } catch {} do { try Keychain(server: URL(string: "https://example.com")!, protocolType: .https).removeAll() } catch {} do { try Keychain(server: URL(string: "https://example.com:443")!, protocolType: .https).removeAll() } catch {} do { try Keychain().removeAll() } catch {} } override func tearDown() { super.tearDown() } // MARK: func testGenericPassword() { do { // Add Keychain items let keychain = Keychain(service: "Twitter") do { try keychain.set("kishikawa_katsumi", key: "username") } catch {} do { try keychain.set("password_1234", key: "password") } catch {} let username = try! keychain.get("username") XCTAssertEqual(username, "kishikawa_katsumi") let password = try! keychain.get("password") XCTAssertEqual(password, "password_1234") } do { // Update Keychain items let keychain = Keychain(service: "Twitter") do { try keychain.set("katsumi_kishikawa", key: "username") } catch {} do { try keychain.set("1234_password", key: "password") } catch {} let username = try! keychain.get("username") XCTAssertEqual(username, "katsumi_kishikawa") let password = try! keychain.get("password") XCTAssertEqual(password, "1234_password") } do { // Remove Keychain items let keychain = Keychain(service: "Twitter") do { try keychain.remove("username") } catch {} do { try keychain.remove("password") } catch {} XCTAssertNil(try! keychain.get("username")) XCTAssertNil(try! keychain.get("password")) } } func testGenericPasswordSubscripting() { do { // Add Keychain items let keychain = Keychain(service: "Twitter", accessGroup: "27AEDK3C9F.shared") keychain["username"] = "kishikawa_katsumi" keychain["password"] = "password_1234" let username = keychain["username"] XCTAssertEqual(username, "kishikawa_katsumi") let password = keychain["password"] XCTAssertEqual(password, "password_1234") } do { // Update Keychain items let keychain = Keychain(service: "Twitter", accessGroup: "27AEDK3C9F.shared") keychain["username"] = "katsumi_kishikawa" keychain["password"] = "1234_password" let username = keychain["username"] XCTAssertEqual(username, "katsumi_kishikawa") let password = keychain["password"] XCTAssertEqual(password, "1234_password") } do { // Remove Keychain items let keychain = Keychain(service: "Twitter", accessGroup: "27AEDK3C9F.shared") keychain["username"] = nil keychain["password"] = nil XCTAssertNil(keychain["username"]) XCTAssertNil(keychain["password"]) } } // MARK: func testInternetPassword() { do { // Add Keychain items let keychain = Keychain(server: URL(string: "https://kishikawakatsumi.com")!, protocolType: .https) do { try keychain.set("kishikawa_katsumi", key: "username") } catch {} do { try keychain.set("password_1234", key: "password") } catch {} let username = try! keychain.get("username") XCTAssertEqual(username, "kishikawa_katsumi") let password = try! keychain.get("password") XCTAssertEqual(password, "password_1234") } do { // Update Keychain items let keychain = Keychain(server: URL(string: "https://kishikawakatsumi.com")!, protocolType: .https) do { try keychain.set("katsumi_kishikawa", key: "username") } catch {} do { try keychain.set("1234_password", key: "password") } catch {} let username = try! keychain.get("username") XCTAssertEqual(username, "katsumi_kishikawa") let password = try! keychain.get("password") XCTAssertEqual(password, "1234_password") } do { // Remove Keychain items let keychain = Keychain(server: URL(string: "https://kishikawakatsumi.com")!, protocolType: .https) do { try keychain.remove("username") } catch {} do { try keychain.remove("password") } catch {} XCTAssertNil(try! keychain.get("username")) XCTAssertNil(try! keychain.get("password")) } } func testInternetPasswordSubscripting() { do { // Add Keychain items let keychain = Keychain(server: URL(string: "https://kishikawakatsumi.com")!, protocolType: .https) keychain["username"] = "kishikawa_katsumi" keychain["password"] = "password_1234" let username = keychain["username"] XCTAssertEqual(username, "kishikawa_katsumi") let password = keychain["password"] XCTAssertEqual(password, "password_1234") } do { // Update Keychain items let keychain = Keychain(server: URL(string: "https://kishikawakatsumi.com")!, protocolType: .https) keychain["username"] = "katsumi_kishikawa" keychain["password"] = "1234_password" let username = keychain["username"] XCTAssertEqual(username, "katsumi_kishikawa") let password = keychain["password"] XCTAssertEqual(password, "1234_password") } do { // Remove Keychain items let keychain = Keychain(server: URL(string: "https://kishikawakatsumi.com")!, protocolType: .https) keychain["username"] = nil keychain["password"] = nil XCTAssertNil(keychain["username"]) XCTAssertNil(keychain["password"]) } } // MARK: func testDefaultInitializer() { let keychain = Keychain() XCTAssertEqual(keychain.service, Bundle.main.bundleIdentifier) XCTAssertEqual(keychain.service, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertNil(keychain.accessGroup) } func testInitializerWithService() { let keychain = Keychain(service: "com.example.github-token") XCTAssertEqual(keychain.service, "com.example.github-token") XCTAssertNil(keychain.accessGroup) } func testInitializerWithAccessGroup() { let keychain = Keychain(accessGroup: "27AEDK3C9F.shared") XCTAssertEqual(keychain.service, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(keychain.accessGroup, "27AEDK3C9F.shared") } func testInitializerWithServiceAndAccessGroup() { let keychain = Keychain(service: "com.example.github-token", accessGroup: "27AEDK3C9F.shared") XCTAssertEqual(keychain.service, "com.example.github-token") XCTAssertEqual(keychain.accessGroup, "27AEDK3C9F.shared") } func testInitializerWithServer() { let server = "https://kishikawakatsumi.com" let url = URL(string: server)! do { let keychain = Keychain(server: server, protocolType: .https) XCTAssertEqual(keychain.server, url) XCTAssertEqual(keychain.protocolType, ProtocolType.https) XCTAssertEqual(keychain.authenticationType, AuthenticationType.default) } do { let keychain = Keychain(server: url, protocolType: .https) XCTAssertEqual(keychain.server, url) XCTAssertEqual(keychain.protocolType, ProtocolType.https) XCTAssertEqual(keychain.authenticationType, AuthenticationType.default) } } func testInitializerWithServerAndAuthenticationType() { let server = "https://kishikawakatsumi.com" let url = URL(string: server)! do { let keychain = Keychain(server: server, protocolType: .https, authenticationType: .htmlForm) XCTAssertEqual(keychain.server, url) XCTAssertEqual(keychain.protocolType, ProtocolType.https) XCTAssertEqual(keychain.authenticationType, AuthenticationType.htmlForm) } do { let keychain = Keychain(server: url, protocolType: .https, authenticationType: .htmlForm) XCTAssertEqual(keychain.server, url) XCTAssertEqual(keychain.protocolType, ProtocolType.https) XCTAssertEqual(keychain.authenticationType, AuthenticationType.htmlForm) } } // MARK: func testContains() { let keychain = Keychain(service: "Twitter") XCTAssertFalse(try! keychain.contains("username"), "not stored username") XCTAssertFalse(try! keychain.contains("password"), "not stored password") do { try keychain.set("kishikawakatsumi", key: "username") } catch {} XCTAssertTrue(try! keychain.contains("username"), "stored username") XCTAssertFalse(try! keychain.contains("password"), "not stored password") do { try keychain.set("password1234", key: "password") } catch {} XCTAssertTrue(try! keychain.contains("username"), "stored username") XCTAssertTrue(try! keychain.contains("password"), "stored password") } // MARK: func testSetString() { let keychain = Keychain(service: "Twitter") XCTAssertNil(try! keychain.get("username"), "not stored username") XCTAssertNil(try! keychain.get("password"), "not stored password") do { try keychain.set("kishikawakatsumi", key: "username") } catch {} XCTAssertEqual(try! keychain.get("username"), "kishikawakatsumi", "stored username") XCTAssertNil(try! keychain.get("password"), "not stored password") do { try keychain.set("password1234", key: "password") } catch {} XCTAssertEqual(try! keychain.get("username"), "kishikawakatsumi", "stored username") XCTAssertEqual(try! keychain.get("password"), "password1234", "stored password") } func testSetStringWithLabel() { let keychain = Keychain(service: "Twitter") .label("Twitter Account") XCTAssertNil(keychain["kishikawakatsumi"], "not stored password") do { let label = try keychain.get("kishikawakatsumi") { (attributes) -> String? in return attributes?.label } XCTAssertNil(label) } catch { XCTFail("error occurred") } keychain["kishikawakatsumi"] = "password1234" XCTAssertEqual(keychain["kishikawakatsumi"], "password1234", "stored password") do { let label = try keychain.get("kishikawakatsumi") { (attributes) -> String? in return attributes?.label } XCTAssertEqual(label, "Twitter Account") } catch { XCTFail("error occurred") } } func testSetStringWithComment() { let keychain = Keychain(service: "Twitter") .comment("Kishikawa Katsumi") XCTAssertNil(keychain["kishikawakatsumi"], "not stored password") do { let comment = try keychain.get("kishikawakatsumi") { (attributes) -> String? in return attributes?.comment } XCTAssertNil(comment) } catch { XCTFail("error occurred") } keychain["kishikawakatsumi"] = "password1234" XCTAssertEqual(keychain["kishikawakatsumi"], "password1234", "stored password") do { let comment = try keychain.get("kishikawakatsumi") { (attributes) -> String? in return attributes?.comment } XCTAssertEqual(comment, "Kishikawa Katsumi") } catch { XCTFail("error occurred") } } func testSetStringWithLabelAndComment() { let keychain = Keychain(service: "Twitter") .label("Twitter Account") .comment("Kishikawa Katsumi") XCTAssertNil(keychain["kishikawakatsumi"], "not stored password") do { let label = try keychain.get("kishikawakatsumi") { (attributes) -> String? in return attributes?.label } XCTAssertNil(label) let comment = try keychain.get("kishikawakatsumi") { (attributes) -> String? in return attributes?.comment } XCTAssertNil(comment) } catch { XCTFail("error occurred") } keychain["kishikawakatsumi"] = "password1234" XCTAssertEqual(keychain["kishikawakatsumi"], "password1234", "stored password") do { let label = try keychain.get("kishikawakatsumi") { (attributes) -> String? in return attributes?.label } XCTAssertEqual(label, "Twitter Account") let comment = try keychain.get("kishikawakatsumi") { (attributes) -> String? in return attributes?.comment } XCTAssertEqual(comment, "Kishikawa Katsumi") } catch { XCTFail("error occurred") } } func testSetData() { let JSONObject = ["username": "kishikawakatsumi", "password": "password1234"] let JSONData = try! JSONSerialization.data(withJSONObject: JSONObject, options: []) let keychain = Keychain(service: "Twitter") XCTAssertNil(try! keychain.getData("JSONData"), "not stored JSON data") do { try keychain.set(JSONData, key: "JSONData") } catch {} XCTAssertEqual(try! keychain.getData("JSONData"), JSONData, "stored JSON data") } func testStringConversionError() { let keychain = Keychain(service: "Twitter") let length = 256 let data = NSMutableData(length: length)! let bytes = data.mutableBytes.bindMemory(to: UInt8.self, capacity: length) _ = SecRandomCopyBytes(kSecRandomDefault, length, bytes) do { try keychain.set(data as Data, key: "RandomData") let _ = try keychain.getString("RandomData") XCTFail("no error occurred") } catch let error as NSError { XCTAssertEqual(error.domain, KeychainAccessErrorDomain) XCTAssertEqual(error.code, Int(Status.conversionError.rawValue)) XCTAssertEqual(error.userInfo[NSLocalizedDescriptionKey] as! String, Status.conversionError.localizedDescription) } catch { XCTFail("unexpected error occurred") } do { try keychain.set(data as Data, key: "RandomData") let _ = try keychain.getString("RandomData") XCTFail("no error occurred") } catch Status.conversionError { XCTAssertTrue(true) } catch { XCTFail("unexpected error occurred") } } func testGetPersistentRef() { let keychain = Keychain(service: "Twitter") XCTAssertNil(keychain["kishikawakatsumi"], "not stored password") do { let persistentRef = try keychain.get("kishikawakatsumi") { $0?.persistentRef } XCTAssertNil(persistentRef) } catch { XCTFail("error occurred") } keychain["kishikawakatsumi"] = "password1234" XCTAssertEqual(keychain["kishikawakatsumi"], "password1234", "stored password") do { let persistentRef = try keychain.get("kishikawakatsumi") { $0?.persistentRef } XCTAssertNotNil(persistentRef) } catch { XCTFail("error occurred") } } #if os(iOS) || os(tvOS) func testSetAttributes() { let expectation = self.expectation(description: "Touch ID authentication") DispatchQueue.global(qos: .default).async { do { var attributes = [String: Any]() attributes[String(kSecAttrDescription)] = "Description Test" attributes[String(kSecAttrComment)] = "Comment Test" attributes[String(kSecAttrCreator)] = "Creator Test" attributes[String(kSecAttrType)] = "Type Test" attributes[String(kSecAttrLabel)] = "Label Test" attributes[String(kSecAttrIsInvisible)] = true attributes[String(kSecAttrIsNegative)] = true let keychain = Keychain(service: "Twitter") .attributes(attributes) .accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: .userPresence) XCTAssertNil(keychain["kishikawakatsumi"], "not stored password") do { let attributes = try keychain.get("kishikawakatsumi") { $0 } XCTAssertNil(attributes) } catch { XCTFail("error occurred") } keychain["kishikawakatsumi"] = "password1234" XCTAssertEqual(keychain["kishikawakatsumi"], "password1234", "stored password") do { let attributes = try keychain.get("kishikawakatsumi") { $0 } XCTAssertEqual(attributes?.`class`, ItemClass.genericPassword.rawValue) XCTAssertEqual(attributes?.data, "password1234".data(using: .utf8)) XCTAssertNil(attributes?.ref) XCTAssertNotNil(attributes?.persistentRef) XCTAssertEqual(attributes?.accessible, Accessibility.whenPasscodeSetThisDeviceOnly.rawValue) XCTAssertNotNil(attributes?.accessControl) XCTAssertEqual(attributes?.accessGroup, "27AEDK3C9F.com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertNotNil(attributes?.synchronizable) XCTAssertNotNil(attributes?.creationDate) XCTAssertNotNil(attributes?.modificationDate) XCTAssertEqual(attributes?.attributeDescription, "Description Test") XCTAssertEqual(attributes?.comment, "Comment Test") XCTAssertEqual(attributes?.creator, "Creator Test") XCTAssertEqual(attributes?.type, "Type Test") XCTAssertEqual(attributes?.label, "Label Test") XCTAssertEqual(attributes?.isInvisible, true) XCTAssertEqual(attributes?.isNegative, true) XCTAssertEqual(attributes?.account, "kishikawakatsumi") XCTAssertEqual(attributes?.service, "Twitter") XCTAssertNil(attributes?.generic) XCTAssertNil(attributes?.securityDomain) XCTAssertNil(attributes?.server) XCTAssertNil(attributes?.`protocol`) XCTAssertNil(attributes?.authenticationType) XCTAssertNil(attributes?.port) XCTAssertNil(attributes?.path) XCTAssertEqual(attributes![String(kSecClass)] as? String, ItemClass.genericPassword.rawValue) XCTAssertEqual(attributes![String(kSecValueData)] as? Data, "password1234".data(using: .utf8)) expectation.fulfill() } catch { XCTFail("error occurred") } } } waitForExpectations(timeout: 10.0, handler: nil) do { var attributes = [String: Any]() attributes[String(kSecAttrDescription)] = "Description Test" attributes[String(kSecAttrComment)] = "Comment Test" attributes[String(kSecAttrCreator)] = "Creator Test" attributes[String(kSecAttrType)] = "Type Test" attributes[String(kSecAttrLabel)] = "Label Test" attributes[String(kSecAttrIsInvisible)] = true attributes[String(kSecAttrIsNegative)] = true attributes[String(kSecAttrSecurityDomain)] = "securitydomain" let keychain = Keychain(server: URL(string: "https://example.com:443/api/login/")!, protocolType: .https) .attributes(attributes) XCTAssertNil(keychain["kishikawakatsumi"], "not stored password") do { let attributes = try keychain.get("kishikawakatsumi") { $0 } XCTAssertNil(attributes) } catch { XCTFail("error occurred") } do { keychain["kishikawakatsumi"] = "password1234" XCTAssertEqual(keychain["kishikawakatsumi"], "password1234", "stored password") let attributes = try keychain.get("kishikawakatsumi") { $0 } XCTAssertEqual(attributes?.`class`, ItemClass.internetPassword.rawValue) XCTAssertEqual(attributes?.data, "password1234".data(using: .utf8)) XCTAssertNil(attributes?.ref) XCTAssertNotNil(attributes?.persistentRef) XCTAssertEqual(attributes?.accessible, Accessibility.afterFirstUnlock.rawValue) if #available(iOS 9.0, *) { XCTAssertNil(attributes?.accessControl) } else { XCTAssertNotNil(attributes?.accessControl) } XCTAssertEqual(attributes?.accessGroup, "27AEDK3C9F.com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertNotNil(attributes?.synchronizable) XCTAssertNotNil(attributes?.creationDate) XCTAssertNotNil(attributes?.modificationDate) XCTAssertEqual(attributes?.attributeDescription, "Description Test") XCTAssertEqual(attributes?.comment, "Comment Test") XCTAssertEqual(attributes?.creator, "Creator Test") XCTAssertEqual(attributes?.type, "Type Test") XCTAssertEqual(attributes?.label, "Label Test") XCTAssertEqual(attributes?.isInvisible, true) XCTAssertEqual(attributes?.isNegative, true) XCTAssertEqual(attributes?.account, "kishikawakatsumi") XCTAssertNil(attributes?.service) XCTAssertNil(attributes?.generic) XCTAssertEqual(attributes?.securityDomain, "securitydomain") XCTAssertEqual(attributes?.server, "example.com") XCTAssertEqual(attributes?.`protocol`, ProtocolType.https.rawValue) XCTAssertEqual(attributes?.authenticationType, AuthenticationType.default.rawValue) XCTAssertEqual(attributes?.port, 443) XCTAssertEqual(attributes?.path, "") } catch { XCTFail("error occurred") } do { let keychain = Keychain(server: URL(string: "https://example.com:443/api/login/")!, protocolType: .https) XCTAssertEqual(keychain["kishikawakatsumi"], "password1234", "stored password") keychain["kishikawakatsumi"] = "1234password" XCTAssertEqual(keychain["kishikawakatsumi"], "1234password", "updated password") let attributes = try keychain.get("kishikawakatsumi") { $0 } XCTAssertEqual(attributes?.`class`, ItemClass.internetPassword.rawValue) XCTAssertEqual(attributes?.data, "1234password".data(using: .utf8)) XCTAssertNil(attributes?.ref) XCTAssertNotNil(attributes?.persistentRef) XCTAssertEqual(attributes?.accessible, Accessibility.afterFirstUnlock.rawValue) if #available(iOS 9.0, *) { XCTAssertNil(attributes?.accessControl) } else { XCTAssertNotNil(attributes?.accessControl) } XCTAssertEqual(attributes?.accessGroup, "27AEDK3C9F.com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertNotNil(attributes?.synchronizable) XCTAssertNotNil(attributes?.creationDate) XCTAssertNotNil(attributes?.modificationDate) XCTAssertEqual(attributes?.attributeDescription, "Description Test") XCTAssertEqual(attributes?.comment, "Comment Test") XCTAssertEqual(attributes?.creator, "Creator Test") XCTAssertEqual(attributes?.type, "Type Test") XCTAssertEqual(attributes?.label, "Label Test") XCTAssertEqual(attributes?.isInvisible, true) XCTAssertEqual(attributes?.isNegative, true) XCTAssertEqual(attributes?.account, "kishikawakatsumi") XCTAssertNil(attributes?.service) XCTAssertNil(attributes?.generic) XCTAssertEqual(attributes?.securityDomain, "securitydomain") XCTAssertEqual(attributes?.server, "example.com") XCTAssertEqual(attributes?.`protocol`, ProtocolType.https.rawValue) XCTAssertEqual(attributes?.authenticationType, AuthenticationType.default.rawValue) XCTAssertEqual(attributes?.port, 443) XCTAssertEqual(attributes?.path, "") } catch { XCTFail("error occurred") } do { let keychain = Keychain(server: URL(string: "https://example.com:443/api/login/")!, protocolType: .https) .attributes([String(kSecAttrDescription): "Updated Description"]) XCTAssertEqual(keychain["kishikawakatsumi"], "1234password", "stored password") keychain["kishikawakatsumi"] = "password1234" XCTAssertEqual(keychain["kishikawakatsumi"], "password1234", "updated password") let attributes = keychain[attributes: "kishikawakatsumi"] XCTAssertEqual(attributes?.`class`, ItemClass.internetPassword.rawValue) XCTAssertEqual(attributes?.data, "password1234".data(using: .utf8)) XCTAssertNil(attributes?.ref) XCTAssertNotNil(attributes?.persistentRef) XCTAssertEqual(attributes?.accessible, Accessibility.afterFirstUnlock.rawValue) if #available(iOS 9.0, *) { XCTAssertNil(attributes?.accessControl) } else { XCTAssertNotNil(attributes?.accessControl) } XCTAssertEqual(attributes?.accessGroup, "27AEDK3C9F.com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertNotNil(attributes?.synchronizable) XCTAssertNotNil(attributes?.creationDate) XCTAssertNotNil(attributes?.modificationDate) XCTAssertEqual(attributes?.attributeDescription, "Updated Description") XCTAssertEqual(attributes?.comment, "Comment Test") XCTAssertEqual(attributes?.creator, "Creator Test") XCTAssertEqual(attributes?.type, "Type Test") XCTAssertEqual(attributes?.label, "Label Test") XCTAssertEqual(attributes?.isInvisible, true) XCTAssertEqual(attributes?.isNegative, true) XCTAssertEqual(attributes?.account, "kishikawakatsumi") XCTAssertNil(attributes?.service) XCTAssertNil(attributes?.generic) XCTAssertEqual(attributes?.securityDomain, "securitydomain") XCTAssertEqual(attributes?.server, "example.com") XCTAssertEqual(attributes?.`protocol`, ProtocolType.https.rawValue) XCTAssertEqual(attributes?.authenticationType, AuthenticationType.default.rawValue) XCTAssertEqual(attributes?.port, 443) XCTAssertEqual(attributes?.path, "") } } } #endif func testRemoveString() { let keychain = Keychain(service: "Twitter") XCTAssertNil(try! keychain.get("username"), "not stored username") XCTAssertNil(try! keychain.get("password"), "not stored password") do { try keychain.set("kishikawakatsumi", key: "username") } catch {} XCTAssertEqual(try! keychain.get("username"), "kishikawakatsumi", "stored username") do { try keychain.set("password1234", key: "password") } catch {} XCTAssertEqual(try! keychain.get("password"), "password1234", "stored password") do { try keychain.remove("username") } catch {} XCTAssertNil(try! keychain.get("username"), "removed username") XCTAssertEqual(try! keychain.get("password"), "password1234", "left password") do { try keychain.remove("password") } catch {} XCTAssertNil(try! keychain.get("username"), "removed username") XCTAssertNil(try! keychain.get("password"), "removed password") } func testRemoveData() { let JSONObject = ["username": "kishikawakatsumi", "password": "password1234"] let JSONData = try! JSONSerialization.data(withJSONObject: JSONObject, options: []) let keychain = Keychain(service: "Twitter") XCTAssertNil(try! keychain.getData("JSONData"), "not stored JSON data") do { try keychain.set(JSONData, key: "JSONData") } catch {} XCTAssertEqual(try! keychain.getData("JSONData"), JSONData, "stored JSON data") do { try keychain.remove("JSONData") } catch {} XCTAssertNil(try! keychain.getData("JSONData"), "removed JSON data") } // MARK: func testSubscripting() { let keychain = Keychain(service: "Twitter") XCTAssertNil(keychain["username"], "not stored username") XCTAssertNil(keychain["password"], "not stored password") XCTAssertNil(keychain[string: "username"], "not stored username") XCTAssertNil(keychain[string: "password"], "not stored password") keychain["username"] = "kishikawakatsumi" XCTAssertEqual(keychain["username"], "kishikawakatsumi", "stored username") XCTAssertEqual(keychain[string: "username"], "kishikawakatsumi", "stored username") keychain["password"] = "password1234" XCTAssertEqual(keychain["password"], "password1234", "stored password") XCTAssertEqual(keychain[string: "password"], "password1234", "stored password") keychain[string: "username"] = nil XCTAssertNil(keychain["username"], "removed username") XCTAssertEqual(keychain["password"], "password1234", "left password") XCTAssertNil(keychain[string: "username"], "removed username") XCTAssertEqual(keychain[string: "password"], "password1234", "left password") keychain[string: "password"] = nil XCTAssertNil(keychain["username"], "removed username") XCTAssertNil(keychain["password"], "removed password") XCTAssertNil(keychain[string: "username"], "removed username") XCTAssertNil(keychain[string: "password"], "removed password") let JSONObject = ["username": "kishikawakatsumi", "password": "password1234"] let JSONData = try! JSONSerialization.data(withJSONObject: JSONObject, options: []) XCTAssertNil(keychain[data:"JSONData"], "not stored JSON data") keychain[data: "JSONData"] = JSONData XCTAssertEqual(keychain[data: "JSONData"], JSONData, "stored JSON data") keychain[data: "JSONData"] = nil XCTAssertNil(keychain[data:"JSONData"], "removed JSON data") } // MARK: func testErrorHandling() { do { let keychain = Keychain(service: "Twitter", accessGroup: "27AEDK3C9F.shared") try keychain.removeAll() XCTAssertTrue(true, "no error occurred") } catch { XCTFail("error occurred") } do { let keychain = Keychain(service: "Twitter") try keychain.removeAll() XCTAssertTrue(true, "no error occurred") } catch { XCTFail("error occurred") } do { let keychain = Keychain(server: URL(string: "https://kishikawakatsumi.com")!, protocolType: .https) try keychain.removeAll() XCTAssertTrue(true, "no error occurred") } catch { XCTFail("error occurred") } do { let keychain = Keychain() try keychain.removeAll() XCTAssertTrue(true, "no error occurred") } catch { XCTFail("error occurred") } do { // Add Keychain items let keychain = Keychain(service: "Twitter") do { try keychain.set("kishikawa_katsumi", key: "username") XCTAssertTrue(true, "no error occurred") } catch { XCTFail("error occurred") } do { try keychain.set("password_1234", key: "password") XCTAssertTrue(true, "no error occurred") } catch { XCTFail("error occurred") } do { let username = try keychain.get("username") XCTAssertEqual(username, "kishikawa_katsumi") } catch { XCTFail("error occurred") } do { let password = try keychain.get("password") XCTAssertEqual(password, "password_1234") } catch { XCTFail("error occurred") } } do { // Update Keychain items let keychain = Keychain(service: "Twitter") do { try keychain.set("katsumi_kishikawa", key: "username") XCTAssertTrue(true, "no error occurred") } catch { XCTFail("error occurred") } do { try keychain.set("1234_password", key: "password") XCTAssertTrue(true, "no error occurred") } catch { XCTFail("error occurred") } do { let username = try keychain.get("username") XCTAssertEqual(username, "katsumi_kishikawa") } catch { XCTFail("error occurred") } do { let password = try keychain.get("password") XCTAssertEqual(password, "1234_password") } catch { XCTFail("error occurred") } } do { // Remove Keychain items let keychain = Keychain(service: "Twitter") do { try keychain.remove("username") XCTAssertNil(try! keychain.get("username")) } catch { XCTFail("error occurred") } do { try keychain.remove("password") XCTAssertNil(try! keychain.get("username")) } catch { XCTFail("error occurred") } } } // MARK: func testSetStringWithCustomService() { let username_1 = "kishikawakatsumi" let password_1 = "password1234" let username_2 = "kishikawa_katsumi" let password_2 = "password_1234" let username_3 = "k_katsumi" let password_3 = "12341234" let service_1 = "" let service_2 = "com.kishikawakatsumi.KeychainAccess" let service_3 = "example.com" do { try Keychain().removeAll() } catch {} do { try Keychain(service: service_1).removeAll() } catch {} do { try Keychain(service: service_2).removeAll() } catch {} do { try Keychain(service: service_3).removeAll() } catch {} XCTAssertNil(try! Keychain().get("username"), "not stored username") XCTAssertNil(try! Keychain().get("password"), "not stored password") XCTAssertNil(try! Keychain(service: service_1).get("username"), "not stored username") XCTAssertNil(try! Keychain(service: service_1).get("password"), "not stored password") XCTAssertNil(try! Keychain(service: service_2).get("username"), "not stored username") XCTAssertNil(try! Keychain(service: service_2).get("password"), "not stored password") XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username") XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password") do { try Keychain().set(username_1, key: "username") } catch {} XCTAssertEqual(try! Keychain().get("username"), username_1, "stored username") XCTAssertNil(try! Keychain(service: service_1).get("password"), "not stored password") XCTAssertNil(try! Keychain(service: service_2).get("username"), "not stored username") XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username") do { try Keychain(service: service_1).set(username_1, key: "username") } catch {} XCTAssertEqual(try! Keychain().get("username"), username_1, "stored username") XCTAssertEqual(try! Keychain(service: service_1).get("username"), username_1, "stored username") XCTAssertNil(try! Keychain(service: service_2).get("username"), "not stored username") XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username") do { try Keychain(service: service_2).set(username_2, key: "username") } catch {} XCTAssertEqual(try! Keychain().get("username"), username_1, "stored username") XCTAssertEqual(try! Keychain(service: service_1).get("username"), username_1, "stored username") XCTAssertEqual(try! Keychain(service: service_2).get("username"), username_2, "stored username") XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username") do { try Keychain(service: service_3).set(username_3, key: "username") } catch {} XCTAssertEqual(try! Keychain().get("username"), username_1, "stored username") XCTAssertEqual(try! Keychain(service: service_1).get("username"), username_1, "stored username") XCTAssertEqual(try! Keychain(service: service_2).get("username"), username_2, "stored username") XCTAssertEqual(try! Keychain(service: service_3).get("username"), username_3, "stored username") do { try Keychain().set(password_1, key: "password") } catch {} XCTAssertEqual(try! Keychain().get("password"), password_1, "stored password") XCTAssertNil(try! Keychain(service: service_1).get("password"), "not stored password") XCTAssertNil(try! Keychain(service: service_2).get("password"), "not stored password") XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password") do { try Keychain(service: service_1).set(password_1, key: "password") } catch {} XCTAssertEqual(try! Keychain().get("password"), password_1, "stored password") XCTAssertEqual(try! Keychain(service: service_1).get("password"), password_1, "stored password") XCTAssertNil(try! Keychain(service: service_2).get("password"), "not stored password") XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password") do { try Keychain(service: service_2).set(password_2, key: "password") } catch {} XCTAssertEqual(try! Keychain().get("password"), password_1, "stored password") XCTAssertEqual(try! Keychain(service: service_1).get("password"), password_1, "stored password") XCTAssertEqual(try! Keychain(service: service_2).get("password"), password_2, "stored password") XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password") do { try Keychain(service: service_3).set(password_3, key: "password") } catch {} XCTAssertEqual(try! Keychain().get("password"), password_1, "stored password") XCTAssertEqual(try! Keychain(service: service_1).get("password"), password_1, "stored password") XCTAssertEqual(try! Keychain(service: service_2).get("password"), password_2, "stored password") XCTAssertEqual(try! Keychain(service: service_3).get("password"), password_3, "stored password") do { try Keychain().remove("username") } catch {} XCTAssertNil(try! Keychain().get("username"), "removed username") XCTAssertEqual(try! Keychain(service: service_1).get("username"), username_1, "left username") XCTAssertEqual(try! Keychain(service: service_2).get("username"), username_2, "left username") XCTAssertEqual(try! Keychain(service: service_3).get("username"), username_3, "left username") do { try Keychain(service: service_1).remove("username") } catch {} XCTAssertNil(try! Keychain().get("username"), "removed username") XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username") XCTAssertEqual(try! Keychain(service: service_2).get("username"), username_2, "left username") XCTAssertEqual(try! Keychain(service: service_3).get("username"), username_3, "left username") do { try Keychain(service: service_2).remove("username") } catch {} XCTAssertNil(try! Keychain().get("username"), "removed username") XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username") XCTAssertNil(try! Keychain(service: service_2).get("username"), "removed username") XCTAssertEqual(try! Keychain(service: service_3).get("username"), username_3, "left username") do { try Keychain(service: service_3).remove("username") } catch {} XCTAssertNil(try! Keychain().get("username"), "removed username") XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username") XCTAssertNil(try! Keychain(service: service_2).get("username"), "removed username") XCTAssertNil(try! Keychain(service: service_3).get("username"), "removed username") do { try Keychain().remove("password") } catch {} XCTAssertNil(try! Keychain().get("password"), "removed password") XCTAssertEqual(try! Keychain(service: service_1).get("password"), password_1, "left password") XCTAssertEqual(try! Keychain(service: service_2).get("password"), password_2, "left password") XCTAssertEqual(try! Keychain(service: service_3).get("password"), password_3, "left password") do { try Keychain(service: service_1).remove("password") } catch {} XCTAssertNil(try! Keychain().get("password"), "removed password") XCTAssertNil(try! Keychain(service: service_1).get("password"), "removed password") XCTAssertEqual(try! Keychain(service: service_2).get("password"), password_2, "left password") XCTAssertEqual(try! Keychain(service: service_3).get("password"), password_3, "left password") do { try Keychain(service: service_2).remove("password") } catch {} XCTAssertNil(try! Keychain().get("password"), "removed password") XCTAssertNil(try! Keychain(service: service_1).get("password"), "removed password") XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password") XCTAssertEqual(try! Keychain(service: service_3).get("password"), password_3, "left password") do { try Keychain(service: service_3).remove("password") } catch {} XCTAssertNil(try! Keychain().get("password"), "removed password") XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password") XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password") XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password") } // MARK: func testProperties() { guard #available(OSX 10.10, *) else { return } let keychain = Keychain() XCTAssertEqual(keychain.synchronizable, false) XCTAssertEqual(keychain.synchronizable(true).synchronizable, true) XCTAssertEqual(keychain.synchronizable(false).synchronizable, false) XCTAssertEqual(keychain.accessibility(.afterFirstUnlock).accessibility, Accessibility.afterFirstUnlock) XCTAssertEqual(keychain.accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: .userPresence).accessibility, Accessibility.whenPasscodeSetThisDeviceOnly) XCTAssertEqual(keychain.accessibility(.whenPasscodeSetThisDeviceOnly, authenticationPolicy: .userPresence).authenticationPolicy, AuthenticationPolicy.userPresence) XCTAssertNil(keychain.label) XCTAssertEqual(keychain.label("Label").label, "Label") XCTAssertNil(keychain.comment) XCTAssertEqual(keychain.comment("Comment").comment, "Comment") XCTAssertEqual(keychain.authenticationPrompt("Prompt").authenticationPrompt, "Prompt") } // MARK: func testAllKeys() { do { let keychain = Keychain() keychain["key1"] = "value1" keychain["key2"] = "value2" keychain["key3"] = "value3" let allKeys = keychain.allKeys() XCTAssertEqual(allKeys.count, 3) XCTAssertEqual(allKeys.sorted(), ["key1", "key2", "key3"]) let allItems = keychain.allItems() XCTAssertEqual(allItems.count, 3) let sortedItems = allItems.sorted { (item1, item2) -> Bool in let key1 = item1["key"] as! String let key2 = item2["key"] as! String return key1.compare(key2) == .orderedAscending || key1.compare(key2) == .orderedSame } #if !os(OSX) XCTAssertEqual(sortedItems[0]["accessGroup"] as? String, "27AEDK3C9F.com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[0]["synchronizable"] as? String, "false") XCTAssertEqual(sortedItems[0]["service"] as? String, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[0]["value"] as? String, "value1") XCTAssertEqual(sortedItems[0]["key"] as? String, "key1") XCTAssertEqual(sortedItems[0]["class"] as? String, "GenericPassword") XCTAssertEqual(sortedItems[0]["accessibility"] as? String, "AfterFirstUnlock") XCTAssertEqual(sortedItems[1]["accessGroup"] as? String, "27AEDK3C9F.com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[1]["synchronizable"] as? String, "false") XCTAssertEqual(sortedItems[1]["service"] as? String, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[1]["value"] as? String, "value2") XCTAssertEqual(sortedItems[1]["key"] as? String, "key2") XCTAssertEqual(sortedItems[1]["class"] as? String, "GenericPassword") XCTAssertEqual(sortedItems[1]["accessibility"] as? String, "AfterFirstUnlock") XCTAssertEqual(sortedItems[2]["accessGroup"] as? String, "27AEDK3C9F.com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[2]["synchronizable"] as? String, "false") XCTAssertEqual(sortedItems[2]["service"] as? String, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[2]["value"] as? String, "value3") XCTAssertEqual(sortedItems[2]["key"] as? String, "key3") XCTAssertEqual(sortedItems[2]["class"] as? String, "GenericPassword") XCTAssertEqual(sortedItems[2]["accessibility"] as? String, "AfterFirstUnlock") #else XCTAssertEqual(sortedItems[0]["service"] as? String, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[0]["key"] as? String, "key1") XCTAssertEqual(sortedItems[0]["class"] as? String, "GenericPassword") XCTAssertEqual(sortedItems[1]["service"] as? String, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[1]["key"] as? String, "key2") XCTAssertEqual(sortedItems[1]["class"] as? String, "GenericPassword") XCTAssertEqual(sortedItems[2]["service"] as? String, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[2]["key"] as? String, "key3") XCTAssertEqual(sortedItems[2]["class"] as? String, "GenericPassword") #endif } do { let keychain = Keychain(service: "service1") try! keychain .synchronizable(true) .accessibility(.whenUnlockedThisDeviceOnly) .set("service1_value1", key: "service1_key1") try! keychain .synchronizable(false) .accessibility(.afterFirstUnlockThisDeviceOnly) .set("service1_value2", key: "service1_key2") let allKeys = keychain.allKeys() XCTAssertEqual(allKeys.count, 2) XCTAssertEqual(allKeys.sorted(), ["service1_key1", "service1_key2"]) let allItems = keychain.allItems() XCTAssertEqual(allItems.count, 2) let sortedItems = allItems.sorted { (item1, item2) -> Bool in let key1 = item1["key"] as! String let key2 = item2["key"] as! String return key1.compare(key2) == .orderedAscending || key1.compare(key2) == .orderedSame } #if !os(OSX) XCTAssertEqual(sortedItems[0]["accessGroup"] as? String, "27AEDK3C9F.com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[0]["synchronizable"] as? String, "true") XCTAssertEqual(sortedItems[0]["service"] as? String, "service1") XCTAssertEqual(sortedItems[0]["value"] as? String, "service1_value1") XCTAssertEqual(sortedItems[0]["key"] as? String, "service1_key1") XCTAssertEqual(sortedItems[0]["class"] as? String, "GenericPassword") XCTAssertEqual(sortedItems[0]["accessibility"] as? String, "WhenUnlockedThisDeviceOnly") XCTAssertEqual(sortedItems[1]["accessGroup"] as? String, "27AEDK3C9F.com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedItems[1]["synchronizable"] as? String, "false") XCTAssertEqual(sortedItems[1]["service"] as? String, "service1") XCTAssertEqual(sortedItems[1]["value"] as? String, "service1_value2") XCTAssertEqual(sortedItems[1]["key"] as? String, "service1_key2") XCTAssertEqual(sortedItems[1]["class"] as? String, "GenericPassword") XCTAssertEqual(sortedItems[1]["accessibility"] as? String, "AfterFirstUnlockThisDeviceOnly") #else XCTAssertEqual(sortedItems[0]["service"] as? String, "service1") XCTAssertEqual(sortedItems[0]["key"] as? String, "service1_key1") XCTAssertEqual(sortedItems[0]["class"] as? String, "GenericPassword") XCTAssertEqual(sortedItems[1]["service"] as? String, "service1") XCTAssertEqual(sortedItems[1]["key"] as? String, "service1_key2") XCTAssertEqual(sortedItems[1]["class"] as? String, "GenericPassword") #endif } do { let keychain = Keychain(server: "https://google.com", protocolType: .https) try! keychain .synchronizable(false) .accessibility(.alwaysThisDeviceOnly) .set("google.com_value1", key: "google.com_key1") try! keychain .synchronizable(true) .accessibility(.always) .set("google.com_value2", key: "google.com_key2") let allKeys = keychain.allKeys() XCTAssertEqual(allKeys.count, 2) XCTAssertEqual(allKeys.sorted(), ["google.com_key1", "google.com_key2"]) let allItems = keychain.allItems() XCTAssertEqual(allItems.count, 2) let sortedItems = allItems.sorted { (item1, item2) -> Bool in let key1 = item1["key"] as! String let key2 = item2["key"] as! String return key1.compare(key2) == .orderedAscending || key1.compare(key2) == .orderedSame } #if !os(OSX) XCTAssertEqual(sortedItems[0]["synchronizable"] as? String, "false") XCTAssertEqual(sortedItems[0]["value"] as? String, "google.com_value1") XCTAssertEqual(sortedItems[0]["key"] as? String, "google.com_key1") XCTAssertEqual(sortedItems[0]["server"] as? String, "google.com") XCTAssertEqual(sortedItems[0]["class"] as? String, "InternetPassword") XCTAssertEqual(sortedItems[0]["authenticationType"] as? String, "Default") XCTAssertEqual(sortedItems[0]["protocol"] as? String, "HTTPS") XCTAssertEqual(sortedItems[0]["accessibility"] as? String, "AlwaysThisDeviceOnly") XCTAssertEqual(sortedItems[1]["synchronizable"] as? String, "true") XCTAssertEqual(sortedItems[1]["value"] as? String, "google.com_value2") XCTAssertEqual(sortedItems[1]["key"] as? String, "google.com_key2") XCTAssertEqual(sortedItems[1]["server"] as? String, "google.com") XCTAssertEqual(sortedItems[1]["class"] as? String, "InternetPassword") XCTAssertEqual(sortedItems[1]["authenticationType"] as? String, "Default") XCTAssertEqual(sortedItems[1]["protocol"] as? String, "HTTPS") XCTAssertEqual(sortedItems[1]["accessibility"] as? String, "Always") #else XCTAssertEqual(sortedItems[0]["key"] as? String, "google.com_key1") XCTAssertEqual(sortedItems[0]["server"] as? String, "google.com") XCTAssertEqual(sortedItems[0]["class"] as? String, "InternetPassword") XCTAssertEqual(sortedItems[0]["authenticationType"] as? String, "Default") XCTAssertEqual(sortedItems[0]["protocol"] as? String, "HTTPS") XCTAssertEqual(sortedItems[1]["key"] as? String, "google.com_key2") XCTAssertEqual(sortedItems[1]["server"] as? String, "google.com") XCTAssertEqual(sortedItems[1]["class"] as? String, "InternetPassword") XCTAssertEqual(sortedItems[1]["authenticationType"] as? String, "Default") XCTAssertEqual(sortedItems[1]["protocol"] as? String, "HTTPS") #endif } #if !os(OSX) do { let allKeys = Keychain.allKeys(.genericPassword) XCTAssertEqual(allKeys.count, 5) let sortedKeys = allKeys.sorted { (key1, key2) -> Bool in return key1.1.compare(key2.1) == .orderedAscending || key1.1.compare(key2.1) == .orderedSame } XCTAssertEqual(sortedKeys[0].0, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedKeys[0].1, "key1") XCTAssertEqual(sortedKeys[1].0, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedKeys[1].1, "key2") XCTAssertEqual(sortedKeys[2].0, "com.kishikawakatsumi.KeychainAccess.TestHost") XCTAssertEqual(sortedKeys[2].1, "key3") XCTAssertEqual(sortedKeys[3].0, "service1") XCTAssertEqual(sortedKeys[3].1, "service1_key1") XCTAssertEqual(sortedKeys[4].0, "service1") XCTAssertEqual(sortedKeys[4].1, "service1_key2") } do { let allKeys = Keychain.allKeys(.internetPassword) XCTAssertEqual(allKeys.count, 2) let sortedKeys = allKeys.sorted { (key1, key2) -> Bool in return key1.1.compare(key2.1) == .orderedAscending || key1.1.compare(key2.1) == .orderedSame } XCTAssertEqual(sortedKeys[0].0, "google.com") XCTAssertEqual(sortedKeys[0].1, "google.com_key1") XCTAssertEqual(sortedKeys[1].0, "google.com") XCTAssertEqual(sortedKeys[1].1, "google.com_key2") } #endif } func testDescription() { do { let keychain = Keychain() XCTAssertEqual(keychain.description, "[]") XCTAssertEqual(keychain.debugDescription, "[]") } } // MARK: func testAuthenticationPolicy() { guard #available(iOS 9.0, OSX 10.11, *) else { return } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.userPresence] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } #if os(iOS) do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.userPresence, .applicationPassword] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.userPresence, .applicationPassword, .privateKeyUsage] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.applicationPassword] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.applicationPassword, .privateKeyUsage] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.privateKeyUsage] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDAny] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDAny, .devicePasscode] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDAny, .applicationPassword] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDAny, .applicationPassword, .privateKeyUsage] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDCurrentSet] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDCurrentSet, .devicePasscode] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDCurrentSet, .applicationPassword] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDCurrentSet, .applicationPassword, .privateKeyUsage] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDAny, .or, .devicePasscode] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.touchIDAny, .and, .devicePasscode] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } #endif #if os(OSX) do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.userPresence] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } do { let accessibility: Accessibility = .whenPasscodeSetThisDeviceOnly let policy: AuthenticationPolicy = [.devicePasscode] let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue) var error: Unmanaged? let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue as CFTypeRef, flags, &error) XCTAssertNil(error) XCTAssertNotNil(accessControl) } #endif } }