SecItemAdd 在 iOS10模拟器的 Xcode 8中总是返回错误 -34018

更新 : 这个问题在 Xcode 8.2中已经修复。 Keychain 在模拟器中工作,但是没有启用 Keychain 共享。

为什么在调用 SecItemAdd函数 在 Xcode 8/iOS 10模拟器中一直都是收到错误 -34018?

繁殖的步骤

在 Xcode 8中创建一个新的 Single page iOS 应用程序项目。 在 viewDidLoad中运行以下代码(或打开 这个 Xcode 项目)。

let itemKey = "My key"
let itemValue = "My secretive bee 🐝"


// Remove from Keychain
// ----------------


let queryDelete: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: itemKey as AnyObject
]


let resultCodeDelete = SecItemDelete(queryDelete as CFDictionary)


if resultCodeDelete != noErr {
print("Error deleting from Keychain: \(resultCodeDelete)")
}




// Add to keychain
// ----------------


guard let valueData = itemValue.data(using: String.Encoding.utf8) else {
print("🐣🐣🐣🐣🐣🐣🐣🐣🐣🐣 Error saving text to Keychain")
return
}


let queryAdd: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: itemKey as AnyObject,
kSecValueData as String: valueData as AnyObject,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]


let resultCode = SecItemAdd(queryAdd as CFDictionary, nil)


if resultCode != noErr {
print("🐝🐝🐝🐝🐝🐝🐝🐝🐝 Error saving to Keychain: \(resultCode).")
} else {
print("🍀🍀🍀🍀🍀🍀🍀🍀🍀 Saved to keychain successfully.")
}

预期成果

项被添加到钥匙链。

实际结果

函数 SecItemAdd 返回以下错误代码: -34018

版本

Xcode 版本8.1(8B62) ,macOS Sierra 10.12.1。

配置

自从 Beta 2在 iOS10模拟器中测试以来,Xcode 8中总是出现这种情况。

在 iOS 9.3模拟器中测试时,Xcode 8中不会出现这种情况。

演示

Https://dl.dropboxusercontent.com/u/11143285/2016/07/keychainbugdemo.zip

参考文献

雷达: https://openradar.appspot.com/27422249

苹果开发者论坛: https://forums.developer.apple.com/message/179846

这个问题不同于下面的文章,因为它发生在 Xcode 8.SecItemAdd 和 SecItemCopymatch 返回错误代码 -34018(errSecMissingEntitlement)中的 始终如一

32953 次浏览

I was able to work around this in my app by adding Keychain Access Groups to the Entitlements file. I turned on the Keychain Sharing switch in the Capabilities section in your test app, and it is working for me as well.

Screenshot of turning on the switch

Item to add to entitlements:

<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.evgenii.KeychainBugDemo</string>
</array>

I have only tried this on macOS Sierra (10.12), so I'm not sure if it will work for you on 10.11.5.

I got an error while signing with email, creating a new user or with sign out using firebase.

The error was:

firauth error domain code 17995

I turned on the Keychain Sharing switch in the Capabilities section in your test app, and it is working for me as well.

This can happen if you have a test target that does not have a host app. To fix

  1. add a dummy host app : enter image description here

  2. Enable automatic code signing and add a team :

enter image description here

  1. Enable keychain sharing in capabilities

enter image description here

I was looking for a solution that didn't use Keychain sharing, as that wasn't the feature I was looking for. The developer forum Seems to have a good work around from EvergreenCoder that you can limit in scope to only the iOS 10 simulator (as this seems to be the only affected simulator). From the post:

The issue seems to be that there must be at least one entitlement in order for Xcode to properly add the "application-identifier" enttilement to the built application. This is why keychain sharing seems to be a solution but it is only indirectly so: any other entitlement seems to work fine.

You can create a .plist like so:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-/
<plist version="1.0">
<dict>
<key>get-task-allow</key>
<true/>
</dict>
</plist>

and provide a path to that file under Build Settings in

Code Signing->Debug->Simulater iOS 10 SDK->($SRCROOT)/your-path-to-file

As stated in the post, this entitlement just allows the debugger to be attached.

In Xcode 8.1 GM Release Notes Apple acknowledged the problem and suggested a cleaner workaround:

Keychain APIs may fail to work in the Simulator if your entitlements file doesn’t contain a value for the application-identifier entitlement. (28338972) Workaround: Add a user-defined build setting to your target named ENTITLEMENTS_REQUIRED and set the value to YES. This will cause Xcode to automatically insert an application-identifier entitlement when building.

Note that from what I have tried, it only works in Xcode 8.1. Although the text can mislead you into a build setting, what you need to do is add this to your Environment Variables, in your scheme.

enter image description here

Xcode 8.2 will solve this:

Resolved in Xcode 8.2 beta - IDE Keychain APIs work correctly in Simulator. (28338972)

I had a similar issue, though I was getting the -34018 error when trying to run on device. I am using XCode 8.1 on Sierra with iOS 10.1. I work on a team and suddenly had this issue when we switched to "Automatically manage signing" in the project settings. When I turn this off and manually select my profile, everything works fine. I ended up having to delete my developer certificate from my keychain, then re-select "Automatically manage signing". On the next build, it generated a new signing certificate for me and everything works fine now. I'm still not sure what caused the issue as the other cert worked fine when manually selected, but not when being managed by XCode. Hope this helps stop an hours long headache for someone else.

It works after enabling the keychain sharing in capabilities.

I was able to solve this issue in Xcode 11 without any entitlement adjustments.

I simply added a new app target to my framework's project called MyFrameworkTestsHostApp.

Then I selected the MyFrameworkTests target and chose its Host Application as MyFrameworkTestsHostApp.

There 3 steps to take to resolve this issue quickly.

  1. Turn on Keychain sharing in your project capabilities.
  2. Select Automatic Provisioning with a profile
  3. Ensure your custom entitlement option is set to Entitlement.plist.

This will do the magic