iOS密钥链写入值导致错误代码-34018

我有一个iOS应用程序,在钥匙串中存储一些敏感信息。 在将值写入钥匙串时,出现错误代码-34018。

我目前正在使用苹果的iOS KeyChainItemWrapper类。

以下两行代码都会收到相同的错误代码。

OSStatus res1 = SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes); OSStatus res = SecItemUpdate((__bridge CFDictionaryRef)updateItem, (__bridge CFDictionaryRef)tempCheck); 

这个问题并不是每次都会发生,但是是间歇性的。 一旦我得到这个错误,我不能再给钥匙串写任何值了。

我已经打印出这样的错误描述:

 NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:res userInfo:nil]; 

这是错误打印出来的东西:

 Error: Error Domain=NSOSStatusErrorDomain Code=-34018 "The operation couldn't be completed. (OSStatus error -34018.)" 

似乎这是钥匙串中的一个错误,只有当您从xcode启动您的应用程序时才会出现这个错误。 看到这里: https : //github.com/soffes/sskeychain/issues/52

我们debugging了很多,当从后台启动应用程序时,这似乎是访问钥匙串的一个问题。 这只有在debugging器(即从Xcode启动时)才会发生。 我们认为这个问题在我们的案例中可能与debugging器保持运行应用程序有关,即使它应该被操作系统杀死。 我们试着运行应用程序,然后把它放在后台,并启动许多其他应用程序占用内存。 debugging器出现错误时从后台恢复应用程序,而没有debugging器它没有(我们至less运行了10个testing)。

如果有人会回来这个错误,并与iOS10 XCode8 ,可能你必须启用KeyChain共享在选项卡Capabilities

激活KeychainShare ON 在这里输入图像说明

正如其他人所提到的,这是一个钥匙串漏洞,苹果公司至less在2015年中期就已经意识到了这个漏洞。

但截至2016年3月22日,苹果已经表示:

我们相信这些问题已经在iOS 9.3中解决了。

iOS 9.3于2016年3月21日发布。

请参阅线程: https : //forums.developer.apple.com/thread/4743

引用苹果员工的回应:

2016年3月22日上午3:28

好的,这是最新的。 这是一个复杂的问题,有多种可能的原因:

  • 一些问题的实例是由不正确的应用程序签名造成的。 您可以很容易地区分这种情况,因为问题是100%可重现的。

  • 这个问题的一些实例是由iOS如何支持应用程序开发(r。23,991,853)中的一个错误引起的。 由于OS(23,770,418)的另一个缺陷掩盖了它的效果,这意味着当设备处于内存压力下时,问题才会出现。

    我们相信这些问题已经在iOS 9.3中解决了。

  • 我们怀疑这个问题可能还有更多的原因。

因此,如果您在运行iOS 9.3或更高版本的用户设备(未经Xcode讨论的设备)上看到此问题,请提交有关此问题的错误报告。 尝试将设备系统日志包含在你的bug报告中(我认识到在处理客户设备时可能会非常棘手;一种select是要求客户安装Apple Configurator,以便他们查看系统日志)。 如果你提交了一个bug,请发布你的bug号码,以备logging。

我谨代表苹果,感谢大家为帮助追踪这个相当可怕的问题所做的努力。

分享和享受

在我发现一个快速的“修复”之前,这让我坚持了2个小时 – 重新启动iOS设备

来自http://forums.developer.apple.com/thread/4743上的讨论,

来自用户的小细节

正如其他人所报道的,当通过附带debugging器的Xcode启动时,这个神秘的钥匙串错误是最容易观察到的。 一旦错误开始发生,钥匙串似乎不会自己的权利,无论内存压力, 直到重新启动设备

当我重新启动我的设备时,错误消失了,让我继续testing。 不知道还有什么要做。 在我的情况下,转移到NSUserDefaults或其他存储解决scheme是不可能的。

一个解决这个问题的方法是使用dispatch_async来启动应用程序。 这是从后台打开应用程序时的作品。 另外请确保您在钥匙串上具有kSecAttrAccessibleAfterFirstUnlock辅助function设置。

  dispatch_async(dispatch_get_main_queue(), ^{ // save/write to keychain }) 

根据@卡朗巴的回答。 我find了一个解决方法:

  1. 停止任务以杀死应用程序(如果您已经在运行应用程序)
  2. 手动启动设备上的应用程序。 不要使用Xcode
  3. 使用Xcode重新启动应用程序

我使用苹果的GenericKeychain类:

https://developer.apple.com/library/content/samplecode/GenericKeychain/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007797-Intro-DontLinkElementID_2

 struct KeychainConfiguration { static let serviceName = "MyAppService" /* Specifying an access group to use with `KeychainPasswordItem` instances will create items shared accross both apps. For information on App ID prefixes, see: https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/AppID.html and: https://developer.apple.com/library/ios/technotes/tn2311/_index.html */ // static let accessGroup = "[YOUR APP ID PREFIX].com.example.apple-samplecode.GenericKeychainShared" /* Not specifying an access group to use with `KeychainPasswordItem` instances will create items specific to each app. */ static let accessGroup: String? = nil } 

在这个文件中,我在这行中指定了我的自定义accessGroup static let accessGroup =“[您的APP ID前缀] .com.example.apple-samplecode.GenericKeychainShared”

回到静态之后让accessGroup:String? =零问题没有了。 🙂