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

时间:2013-12-03 06:22:33

标签: ios cocoa keychain sskeychain

有时当我在Xcode上运行设备上的应用程序时,我会尝试访问钥匙串,但由于错误-34018而失败。这与任何记录的钥匙串错误代码都不匹配,并且无法一致地再现。 (可能有30%的时间发生,我不清楚为什么会发生这种情况)。使调试这个问题变得非常困难的原因是完全缺乏文档。知道是什么导致这个以及如何解决它?我正在使用Xcode 5并在设备上运行iOS 7.0.4。

这里有一个未解决的问题:https://github.com/soffes/sskeychain/issues/52

编辑:根据请求添加钥匙串访问代码

我正在使用SSKeychain库与keychain进行交互。这是片段。

#define SERVICE @"default"

@implementation SSKeychain (EXT)

+ (void)setValue:(NSString *)value forKey:(NSString *)key {
    NSError *error = nil;
    BOOL success = NO;
    if (value) {
        success = [self setPassword:value forService:SERVICE account:key error:&error];
    } else {
        success = [self deletePasswordForService:SERVICE account:key error:&error];
    }
    NSAssert(success, @"Unable to set keychain value %@ for key %@ error %@", value, key, error);
    if (!success) {
        LogError(@"Unable to set value to keychain %@", error);
    }
    LogTrace(@"Will set keychain account %@. is to nil? %d", key, value == nil);
    if (value == nil)
        LogWarn(@"Setting keychain %@ to nil!!!", key);
}

+ (NSString *)valueForKey:(NSString *)key {
    NSError *error = nil;
    NSString *value = [self passwordForService:SERVICE account:key error:&error];
    if (error && error.code != errSecItemNotFound) {
        NSAssert(!error, @"Unable to retrieve keychain value for key %@ error %@", key, error);
        LogError(@"Unable to retrieve keychain value for key %@ error %@", key, error);
    }
    return value;
}

+ (BOOL)removeAllValues {
    LogInfo(@"Completely Reseting Keychain");
    return [[self accountsForService:SERVICE] all:^BOOL(NSDictionary *accountInfo) {
        return [self deletePasswordForService:SERVICE account:accountInfo[@"acct"]];
    }];
}

@end

绝大部分时间都很好。有时我会遇到断言故障,我无法写入或读取钥匙串,导致严重的断言失败。

20 个答案:

答案 0 :(得分:45)

  

iOS 10 / XCode 8修复:

     

添加KeyChain权利,转到项目   settings->功能 - > Keychain Sharing->添加Keychain Groups +开启

答案来自Apple:

  

更新:我们终于能够在iOS上重现-34018错误   8.3。这是确定根本原因然后提出修复的第一步。

     

像往常一样,我们无法承诺发布时间表,但这有   影响了许多开发人员,我们真的希望得到解决。

     

早些时候我建议添加一个小延迟   application:didFinishLaunchingWithOptions和   applicationDidBecomeActive:在访问钥匙串之前   解决方法。但是,这实际上似乎没有帮助。这意味着   除了重新启动之外,目前还没有已知的解决方法   应用程序。

     

这个问题似乎与记忆压力有关,所以可能存在   更积极地处理内存警告可以缓解问题

https://forums.developer.apple.com/thread/4743#14441

更新

  

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

     
      
  • 问题的某些情况是由不正确引起的   应用签名。您可以轻松区分这种情况,因为问题   100%可重复。
  •   
  • 问题的某些情况是由a引起的   iOS如何支持应用程序开发的错误(r.23,991,853)。调试   操作系统中的另一个错误(r。   23,770,418)掩盖了它的效果,意味着问题只会出现   当设备处于内存压力下时。我们相信这些问题   已在iOS 9.3中解决。
  •   
  • 我们怀疑可能还有更多原因   这个问题。
  •   
     

因此,如果您在用户设备上看到此问题(一个   那个运行iOS 9.3或更高版本的Xcode尚未与之交谈的,   请提交有关它的错误报告。尝试包含该设备   系统登录你的错误报告(我意识到这可能是棘手的   处理客户设备;一种选择是询问客户   安装Apple Configurator,让他们查看系统日志)。和   如果您确实提交了错误,请发布您的错误号,仅供参考   记录。

     

代表Apple,我要感谢大家   努力帮助追查这个相当可怕的问题。分享和   享受

https://forums.developer.apple.com/thread/4743#126088

答案 1 :(得分:24)

基本上,您必须通过在测试目标中添加以下作为运行脚本来对.xcttest文件夹进行编码。

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

在设备上测试我的钥匙串时,我收到了很多-34018错误,并设法修复它。

如果您的测试目标中不存在此问题,则可能不是解决方案。

答案 2 :(得分:13)

检查source code后。我注意到,钥匙串功能是通过一个在自己的进程中运行的安全守护进程访问的(与应用程序进程分开)。

您的应用和安全流程通过名为XPC的技术“对话”。

如果有必要,可以通过XPC着名的launchd命令启动securityd。您可以检查守护程序是否在活动监视器应用程序中运行(如果在模拟器中运行),并且其父进程已启动。

我的猜测是,由于任何未知原因,安全守护程序可能无法启动或执行速度太慢而且在您尝试使用它时尚未就绪。

也许你可以考虑如何预启动守护进程。

我为没有更精确而道歉。我希望它可以帮助你进一步调查。

答案 3 :(得分:12)

在使用iOS 8 SDK在Xcode 6 beta中构建和运行我的代码后,我观察到类似的行为(它与Xcode 5 / iOS 7一起正常工作)。在Xcode 6中,在iOS模拟器中,SecItemCopyMatching始终返回-34018。它在“功能”选项卡中打开“钥匙串共享”后开始工作。

但是我有另一个问题。我正在开发静态库,由(以及其他)Demo应用程序使用。上面的解决方案适用于Demo应用程序项目,但是当我尝试单元测试我的静态库项目时,我有完全相同的错误。问题是我的静态库项目没有Capabilities选项卡(因为它不是独立的应用程序)。

我已经尝试过JorgeDeCorte在这里发布的解决方案,它在测试目标中进行了编码,但它对我不起作用。

答案 4 :(得分:6)

从Xcode尝试在启动应用时禁用所有断点。 您可以在之后启用它们。

(上述解决方法均不适合我)

答案 5 :(得分:4)

我在运行7.1&amp ;;的模拟器上遇到了同样的问题。 8.0。在进行一些挖掘时,我注意到Apple示例应用程序已启用KeyChain Sharing以获取其目标功能。我为我的应用启用了它,导致创建了一个我使用默认值保留的权利文件,现在我不再收到-34018错误了。这不是理想的,但我现在将使用KeyChain共享选项。

答案 6 :(得分:4)

我也被这个问题所困扰,并且没有其他任何解决方法的成功。 然后我删除了设备本身的配置文件,删除了与我的应用程序相关的所有配置文件以及所有通配符配置文件(这似乎是重点)。 为此,请转到"设备" Xcode中的窗口并右键单击(已连接)手机:

点击"显示配置文件"并删除相关的,特别是团队档案:

包括带星号的那些。 重新安装应用程序后,一切都恢复正常。

答案 7 :(得分:3)

在某些情况下,对.xctest包进行编码并不像听起来那么简单。主要是JorgeDeCorte对他的answer是正确的,对于大多数开发者而言,给定的短线为Run Script就足够了。

codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"

但是当您的钥匙串中有多个证书时,这将失败并显示以下行

iPhone Developer: ambiguous (matches "iPhone Developer: Your Name (ABC123DEF45)" and "iPhone Developer: Your Name (123ABC456DE)"

即使有多个证书也能获得正确证书的解决方案就是这个简短的脚本。当然这并不理想,但据我所知,你没有机会获得Xcode发现并用于签署.app的证书。

echo "codesign --verify --force --sign \"$CODE_SIGN_IDENTITY\" \"$CODESIGNING_FOLDER_PATH\""
IDENTITIES=`security find-identity -v -s "Code Signing" | grep "iPhone Developer" | awk '{ print $2 }'`

for SHA in $IDENTITIES; do
    codesign --verify --force --sign $SHA "$CODESIGNING_FOLDER_PATH"
    if [ $? -eq 0 ]; then
        echo "Matching identity found: $SHA"
        exit 0
    fi
done;

exit 1

答案 8 :(得分:3)

我已经解决了这个问题(我认为)。我的设备上有一个通配符配置文件,显示它没有有效的签名身份。我的应用程序的配置文件也是有效的。当我删除通配符配置文件时,我停止了-34018错误。

我还确保目标的Build Settings的Code Signing部分中列出的代码签名标识和配置文件与应用程序的相同(不是通用的" iPhone Developer" one )

答案 9 :(得分:2)

我的应用(iOS 8.4)中很少出现 -34018 错误。经过一些调查后,我发现当应用程序从钥匙串经常请求数据时会出现此问题。
例如,在我的情况下,它是来自不同应用程序模块的同时对一个特定键的两个读取请求 为了解决这个问题,我刚刚在内存中添加了缓存此值

答案 10 :(得分:1)

我遇到了同样的问题,突然出现在Xcode 6.2,iPhone 6,iOS 8.3的测试设备上运行。要清楚,在运行Xcode测试时没有经历过这种情况,而是在我的设备上运行实际的应用程序时。在模拟器中它很好,并且在应用程序本身上运行它直到最近一直很好。

我尝试了我可以在这里找到的所有建议,例如删除我设备上的配置文件(我删除了所有这些),暂时启用了项目中的Keychain Sharing功能(即使我们真的不需要),确保我在Xcode中的开发帐户完全刷新所有证书和配置文件等。没有任何帮助。

然后我暂时将可访问性级别从kSecAttrAccessibleAfterFirstUnlock更改为kSecAttrAccessibleAlwaysThisDeviceOnly,运行应用程序,它运行正常并且能够写入Keychain。然后我把它改回kSecAttrAccessibleAfterFirstUnlock,问题似乎已经“永久地”消失了。

答案 11 :(得分:1)

刚刚被Xcode 8 Beta 3上的这个错误所困扰。打开钥匙串共享似乎是唯一的解决方案。

答案 12 :(得分:1)

我有同样的问题。通过设置钥匙串共享来修复它。

答案 13 :(得分:1)

(这不是OP问题的直接答案,但可能有助于其他人)

在将Xcode从7.3.1版更新到8.0版后,开始在模拟器中始终获得钥匙串错误-34018。

根据daidai's answer提示,

  

问题的某些情况是由错误的应用签名引起的。您可以轻松区分这种情况,因为问题是100%可重现的。

发现在目标的签名部分中,Provisioning Profile已经以某种方式设置为None。

但是,在这种情况下,将Provisioning Profile字段设置为有效值不足以解决问题。

进一步调查显示推送通知权利也显示错误。它说“将推送通知功能添加到您的应用程序ID”。步骤已完成,但步骤“将推送通知权利添加到您的权利文件”不是。

按“修复问题”以修复推送通知问题后,解决了钥匙串错误。

对于此特定目标,“Keychain Sharing”权利已在之前的某个时间启用。关闭它并没有导致钥匙串错误再次出现,因此不清楚在这种情况下是否有必要。

答案 14 :(得分:0)

对我来说,这是一个应用程序签名问题。我只是切换到Xcode中正确的签名团队,而错误不再发生

答案 15 :(得分:0)

什么对我有用

  • 打开钥匙串共享。
  • 尽可能少地使用钥匙串,并将数据缓存在内存,用户首选项,磁盘等中。
  • 如果失败,请重试多次钥匙串CRUD操作。
  • 使用DispatchQueue.sync来存储/删除/更新数据。

答案 16 :(得分:0)

启用项目功能中的钥匙串共享,它应该可以解决问题。 enter image description here

答案 17 :(得分:0)

今天运行SecItemDelete API时遇到了这个-34018问题。 我做的是解决这个问题: 1.关注@ k1th解决方案https://stackoverflow.com/a/33085955/889892 2.在主线程中运行SecItemDelete(以前从主线程中读取它,所以只需将其与删除对齐)。

很抱歉它又回来了:(

答案 18 :(得分:0)

对我有用的唯一解决方案是首先为指定的密钥存储 nil ,然后使用单独的操作存储我的新值。如果我试图覆盖现有值,它将因错误-34018而失败。但只要我先存储 nil ,就会立即成功存储更新后的值。

答案 19 :(得分:0)

在iOS 9中,我关闭了地址清理程序,它开始使用该设备。