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

Posted

技术标签:

【中文标题】SecItemAdd 在 iOS 10 模拟器的 Xcode 8 中总是返回错误 -34018【英文标题】:SecItemAdd always returns error -34018 in Xcode 8 in iOS 10 simulator 【发布时间】:2016-11-22 05:26:50 【问题描述】:

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

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

复制步骤

在 Xcode 8 中创建一个新的单页 iOS 应用项目。 在viewDidLoad 中运行以下代码(或打开this 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。

配置

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

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

演示

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

参考文献

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

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

此问题与以下帖子不同,因为它在 Xcode 8 中始终发生。SecItemAdd and SecItemCopyMatching returns error code -34018 (errSecMissingEntitlement)

【问题讨论】:

这似乎仍然是 Xcode 8 GM 中的一个问题。很高兴看到 Apple 仍处于领先地位... 我真的在挖掘你的控制台日志:-) 该问题已在 Xcode 8.2 中修复,但在 Xcode 9.0 中又出现了! 【参考方案1】:

通过将 钥匙串访问组 添加到权利文件,我能够在我的应用程序中解决此问题。我在您的测试应用的 Capabilities 部分中打开了 Keychain Sharing 开关,它也对我有用。

要添加到权利的项目:

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

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

【讨论】:

这里相同,只是我目前使用的是 Xcode 8 beta 5(使用 iOS 10 模拟器。以前的 beta 版没有出现问题。在真正的 iOS 9 上使用 8b5 进行测试时也不会发生苹果手机)。我注意到功能中的推送通知需要修复(即按下按钮)并同时打开钥匙串共享,不幸的是。然后应用程序不再收到错误。再次关闭关闭 Keychain Sharing后,它仍然有效! 我使用钥匙串作为测试目标,但它失败了 - 我该如何解决这个问题? (因为测试目标中没有能力) @SamJarman 我也有这个问题。我刚刚进入测试目标的构建设置并取消设置权利字段。之后工作正常。 此解决方案适用于应用目标。不幸的是,我正在开发一个使用 KeychainSwift 的 Swift 框架,由于该错误,该框架不再构建。在框架目标中,我无法添加权利文件 afaik。有人知道这种情况的解决方法吗? @JanNash,这是我设法使测试工作的方法evgenii.com/blog/testing-a-keychain-library-in-xcode【参考方案2】:

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

如果您的权利,钥匙串 API 可能无法在模拟器中工作 文件不包含应用程序标识符的值 权利。 (28338972) 解决方法:添加用户定义的构建设置 到名为 ENTITLEMENTS_REQUIRED 的目标并将值设置为 YES。 这将导致 Xcode 自动插入一个 构建时的应用程序标识符权利。

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

Xcode 8.2 将解决这个问题:

在 Xcode 8.2 beta 中已解决 - IDE Keychain API 在 模拟器。 (28338972)

【讨论】:

@Tiago 在 iOS 10.1 模拟器上的 Xcode 8.1 中,发行说明中的​​这个解决方法是否仍然适用于您?我尝试添加此设置(既作为目标上的用户定义设置,也作为方案中的环境变量),在 iOS 10.1 模拟器上运行时,我仍然得到 -34018 返回值。 @guywithmazda,这里也一样。仍然得到 -34018 并尝试了构建设置和环境变量。 对我不起作用,无论是在构建设置中,还是在 Sierra 上的 Xcode 8.1 (8B62) 中作为方案的环境变量。我错过了什么吗? 我使用的是 Xcode 8.2.1,这个问题仍然可以重现。另外,我的问题是如果我没有宿主应用程序,并且我正在创建框架目标,那么如何解决这个问题? 这个问题仍然会影响框架目标的单元测试,因为在这种情况下,测试主机存根需要授权。我们知道这个问题,但如果它对您来说是一个障碍,请提交一个重复的错误。【参考方案3】:

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

    添加虚拟主机应用:

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

    在功能中启用钥匙串共享

【讨论】:

【参考方案4】:

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

错误是:

firauth 错误域代码 17995

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

【讨论】:

【参考方案5】:

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

问题似乎是必须至少有一项权利才能让 Xcode 正确地将“应用程序标识符”权利添加到构建的应用程序中。这就是为什么钥匙串共享似乎是一种解决方案,但它只是间接的:任何其他权利似乎都可以正常工作。

您可以像这样创建.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-&gt;Debug-&gt;Simulater iOS 10 SDK-&gt;($SRCROOT)/your-path-to-file

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

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案7】:

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

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

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

【讨论】:

【参考方案8】:

开启钥匙串共享功能后即可使用。

【讨论】:

【参考方案9】:

有 3 个步骤可以快速解决此问题。

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

这会变魔术

【讨论】:

以上是关于SecItemAdd 在 iOS 10 模拟器的 Xcode 8 中总是返回错误 -34018的主要内容,如果未能解决你的问题,请参考以下文章

SecItemAdd 和 SecItemCopyMatching 返回错误代码 -34018 (errSecMissingEntitlement)

RSA:在 iOS 中加密,在 Java 中解密

OSX 10.10 Yosemite 上的 iOS 6.1 模拟器

Xcode 10.2 无法在 iOS < 10 的模拟器上运行应用程序

在 10.9 上使用 Xcode 6 没有可用的 iOS 8.0 模拟器

iOS 9:SecItemCopyMatching 返回成功状态码,但键为 nil