Keychain distribution + adhoc

To get started, some details: we are developing an iOS application using Swift / Xcode 6.1 GM 2 for development.

We are having some confusing issues with accessing the key chain when distributing ad hoc applications and having problems tracking the cause. All provisioning profiles correspond to the package name of our application. We use TestFlight for distribution, although I do not think this is a problem.

We managed to launch it only on iOS 7 devices that did not have a previously installed application. No iOS 8 device worked ad hoc. The errors that we received at the beginning were 25300 (errSecItemNotFound), and now after resetting the preparation profiles, we get equal to 0 (both when saving at boot time and in the absence of data). Everything works fine when deploying dev with Xcode.

I have separated the code for the keychain shell that we use:

import UIKit import Security let serviceIdentifier = "com.Test.KeychainTest" let kSecClassValue = kSecClass as NSString let kSecAttrAccountValue = kSecAttrAccount as NSString let kSecValueDataValue = kSecValueData as NSString let kSecClassGenericPasswordValue = kSecClassGenericPassword as NSString let kSecAttrServiceValue = kSecAttrService as NSString let kSecMatchLimitValue = kSecMatchLimit as NSString let kSecReturnDataValue = kSecReturnData as NSString let kSecMatchLimitOneValue = kSecMatchLimitOne as NSString class KeychainManager { class func setString(value: NSString, forKey: String) { self.save(serviceIdentifier, key: forKey, data: value) } class func stringForKey(key: String) -> NSString? { var token = self.load(serviceIdentifier, key: key) return token } class func removeItemForKey(key: String) { self.save(serviceIdentifier, key: key, data: "") } class func save(service: NSString, key: String, data: NSString) { var dataFromString: NSData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! // Instantiate a new default keychain query var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, key, dataFromString], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecValueDataValue]) // Delete any existing items SecItemDelete(keychainQuery as CFDictionaryRef) if data == "" { return } // Add the new keychain item var status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil) var alertView = UIAlertView(); alertView.addButtonWithTitle("Ok"); alertView.title = "Status"; alertView.message = "Saving \(status)"; alertView.show(); } class func load(service: NSString, key: String) -> NSString? { // Instantiate a new default keychain query // Tell the query to return a result // Limit our results to one item var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, key, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue]) var dataTypeRef :Unmanaged<AnyObject>? // Search for the keychain items let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef) var alertView = UIAlertView(); alertView.addButtonWithTitle("Ok"); alertView.title = "Status"; alertView.message = "Loading \(status)"; alertView.show(); let opaque = dataTypeRef?.toOpaque() var contentsOfKeychain: NSString? if let op = opaque? { let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue() // Convert the data retrieved from the keychain into a string contentsOfKeychain = NSString(data: retrievedData, encoding: NSUTF8StringEncoding) } else { return nil } return contentsOfKeychain } } 
  • Is there something we could skip?
  • What is the best way to fix this problem? We do not get any errors from the key fob in the log / iPhone configuration utility. For now, I just added some simple warnings to the code to find out what the status of the operation is.
+5
source share
2 answers

Everything in the training profile and key codec seems to be in order. The problem is setting up the Swift compiler ... Change the optimization level for "Release" from "Fastest" to "None", and this seems to solve the problem.

enter image description here

+3
source

Make sure you also specify a value for kSecAttrAccessible . It is also possible to specify a value for kSecAttrAccessControl , which was added in iOS8 .

+1
source

Source: https://habr.com/ru/post/1204813/


All Articles