If a backup to iCloud is made from one device then restored onto another device then items stored in the keychain aren't restored. This isn't what was expected, AFAIA a "ThisDeviceOnly" access setting isn't used, kSecAttrAccessibleAfterFirstUnlock is used (as opposed to kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly) which should have resulted in items being restored onto the other device?
class func createKey() -> NSData?
{
let keychainIdentifierData = kKeychainIdentifier.data(using: String.Encoding.utf8, allowLossyConversion: false)!
let keyData = NSMutableData(length: 64)!
let result = SecRandomCopyBytes(kSecRandomDefault, 64, keyData.mutableBytes.bindMemory(to: UInt8.self, capacity: 64))
if (result != 0)
{
return nil
}
// Store the key in the keychain
let query: [NSString: AnyObject] = [
kSecClass: kSecClassKey,
kSecAttrApplicationTag: keychainIdentifierData as AnyObject,
kSecAttrKeySizeInBits: 512 as AnyObject,
kSecValueData: keyData,
kSecAttrAccessible: kSecAttrAccessibleAfterFirstUnlock
]
let status = SecItemAdd(query as CFDictionary, nil)
if (status != errSecSuccess)
{
return nil
}
return keyData
}
class func getKey() -> NSData?
{
let keychainIdentifierData = kKeychainIdentifier.data(using: String.Encoding.utf8, allowLossyConversion: false)!
// First check in the keychain for an existing key
let query: [NSString: AnyObject] = [
kSecClass: kSecClassKey,
kSecAttrApplicationTag: keychainIdentifierData as AnyObject,
kSecAttrKeySizeInBits: 512 as AnyObject,
kSecReturnData: true as AnyObject
]
// To avoid Swift optimization bug, should use withUnsafeMutablePointer() function to retrieve the keychain item
// See also: https://mcmap.net/q/698615/-querying-ios-keychain-using-swift/27721328#27721328
var dataTypeRef: AnyObject?
let status = withUnsafeMutablePointer(to: &dataTypeRef) { SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) }
if status == errSecSuccess {
return (dataTypeRef as! NSData)
}
return nil
}
kSecAttrAccessibleAfterFirstUnlock
makes the Keychain entry accessible after the first unlock after restarting the device. It has nothing to do with synchronization via iCloud. What you are looking for is presumablykSecAttrSynchronizable
which you should set tokCFBooleanTrue
if you want to enable iCloud synching. But I'm not sure if I understood your Question correctly. – TibbettskSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
counterpart makes entries non-migatory. Therefore you should be able to access the entry. I see nothing obviously wrong with the code. Are you using the samekKeychainIdentifier
? – Tibbetts