SecItemAdd 总是 returns 错误 -34018 在 Xcode 8 在 iOS 10 模拟器

SecItemAdd always returns error -34018 in Xcode 8 in iOS 10 simulator

更新:此问题已在 Xcode 8.2 中修复。钥匙串在模拟器中工作,无需启用钥匙串共享。

为什么我 总是 在调用 SecItemAdd 函数时收到错误 -34018 in Xcode 8 / iOS 10模拟器?

重现步骤

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

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 returns以下错误代码:-34018.

版本

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

配置

在 iOS 10 模拟器中测试时,自 Beta 2 以来总是出现在 Xcode 8 中。

在 Xcode 8 在 iOS 9.3 模拟器中测试时不会出现。

演示

https://dl.dropboxusercontent.com/u/11143285/2016/07/KeychainBugDemo.zip

参考资料

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

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

此问题与以下 post 不同,因为它在 Xcode 8. SecItemAdd and SecItemCopyMatching returns error code -34018 (errSecMissingEntitlement)

一致 发生

通过将 Keychain Access Groups 添加到 Entitlements 文件,我能够在我的应用程序中解决这个问题。我在您的测试应用程序的 Capabilities 部分打开了 Keychain Sharing 开关,它对我也有效。

要添加到权利中的项目:

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

我只在 macOS Sierra (10.12) 上尝试过,所以我不确定它是否适用于 10.11.5。

我在使用电子邮件签名、创建新用户或使用 firebase 注销时遇到错误。

错误是:

firauth error domain code 17995

我在您的测试应用程序的功能部分打开了钥匙串共享开关,它对我也有效。

如果您的测试目标没有宿主应用程序,就会发生这种情况。修复

  1. 添加虚拟主机应用程序:

  2. 启用自动代码签名并添加团队:

  1. 在功能中启用钥匙串共享

我一直在寻找不使用钥匙串共享的解决方案,因为那不是我要找的功能。 The developer forum EvergreenCoder 似乎有一个很好的解决方法,您可以将范围限制在 iOS 10 模拟器(因为这似乎是唯一受影响的模拟器)。来自 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.

您可以像这样创建一个 .plist

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

并在

中的构建设置下提供该文件的路径

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

如 post 中所述,此权利仅允许附加调试器。

Xcode 8.1 GM Release Notes 中,Apple 承认了该问题并提出了更简洁的解决方法:

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.

请注意,根据我的尝试,它仅适用于 Xcode 8.1。尽管文本可能会误导您进入构建设置,但您需要做的是将其添加到您的方案中的环境变量中。

Xcode 8.2 将解决这个问题:

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

我遇到了类似的问题,但在设备上尝试 运行 时遇到了 -34018 错误。我在 Sierra 上使用 XCode 8.1 和 iOS 10.1。我在一个团队工作,当我们在项目设置中切换到 "Automatically manage signing" 时突然遇到了这个问题。当我关闭它并手动 select 我的个人资料时,一切正常。我最终不得不从我的钥匙串中删除我的开发者证书,然后重新 select "Automatically manage signing"。在下一个版本中,它为我生成了一个新的签名证书,现在一切正常。我仍然不确定是什么导致了这个问题,因为另一个证书在手动 selected 时工作正常,但在由 XCode 管理时却没有。希望这有助于阻止其他人长达一个小时的头痛。

在功能中启用钥匙串共享后有效。

我能够在 Xcode 11 中解决此问题,而无需任何权利调整。

我只是在我的框架项目中添加了一个名为 MyFrameworkTestsHostApp 的新应用程序目标。

然后我选择了 MyFrameworkTests 目标并将其主机应用程序选择为 MyFrameworkTestsHostApp。

可采取 3 个步骤快速解决此问题。

  1. 在您的项目功能中开启钥匙串共享。
  2. Select 使用配置文件自动配置
  3. 确保您的自定义授权选项设置为 Entitlement.plist。

这会很神奇