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


116

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

这里有一个关于此的公开问题:https : //github.com/soffes/sskeychain/issues/52

编辑:为每个请求添加钥匙串访问代码

我正在使用该SSKeychain库与钥匙串接口。这是代码段。

#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

大多数时候情况都很好。有时,我会遇到断言失败的问题,因为我无法对钥匙串进行写入或读取,从而导致严重的断言失败。


我有同样的问题,无法重现...我正在使用Apple的KeychainItemWrapper类。有时它会因相同的错误消息而从Google Analytics(分析)崩溃。我正在使用Google Analytics(分析)v3.02。
乔伊,

另外,在AppStore的应用程序中似乎还可以。它仅在开发版本的应用程序中发生。
Joey

2
我有适用于应用程序商店版本的crashlytics,不幸的是,它似乎也在应用程序商店中发生,尽管不如在dev上频繁:/
Tony

3
我正在考虑放弃使用钥匙串,因为这样一来,存储在钥匙串中的数据可能会随机丢失,这对应用程序来说是致命的错误。
托尼

2
我们也看到了这个断断续续的问题。当我们从secItemCopyMatching(包括-34018情况)中获得意外的rc时,将引发异常。我们尝试(勉强地)添加了一种机制,一旦我们从钥匙串中获得所需的值,便将其缓存在应用程序内存中,然后从那里提供它而无需钥匙串访问。但是,现在我们看到的是极少数情况,只有一个钥匙串访问才能获得失败,并显示-34018。有没有人尝试在-340​​18之后重试该操作?
克里斯·马克

Answers:


45

iOS 10 / XCode 8修复:

添加KeyChain权利,转到项目设置->功能->钥匙串共享->添加钥匙串组+打开

来自苹果公司的答案:

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

像往常一样,我们无法承诺发布时间,但是这影响了许多开发人员,我们确实希望解决这个问题。

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

该问题似乎与内存压力有关,因此也许在处理内存警告时更加主动可能会缓解此问题。

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

更新

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

  • 问题的某些实例是由不正确的应用程序签名引起的。您可以轻松地区分这种情况,因为该问题是100%可重现的。
  • 该问题的某些情况是由iOS支持应用开发的错误所致(r。23991853)。由于操作系统中的另一个错误(r。23,770,418)掩盖了其影响,因此调试起来很复杂,这意味着仅当设备处于内存压力下时问题才会出现。我们认为这些问题已在iOS 9.3中得到解决。
  • 我们怀疑可能还有更多导致此问题的原因。

因此,如果您在运行iOS 9.3或更高版本的用户设备(Xcode尚未与之交谈的设备)上看到此问题,请提交有关此问题的错误报告。尝试将设备系统日志包含在错误报告中(我知道在处理客户设备时可能会很棘手;一种选择是要求客户安装Apple Configurator,以便他们查看系统日志)。如果确实要提交错误,请张贴您的错误号,仅供参考。

我谨代表苹果公司感谢每个人为帮助解决这个相当可怕的问题所做的努力。分享和享受

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


2
该问题仍在iOS 9.2,iPhone 5S上重现。
DevGansta '02

1
看起来iOS 9.3应该根据Apple在您链接的线程中的最新回复解决此问题。@daidai,能否请您使用此新信息更新您的答案?
jf

1
@YoonLee在iOS10上也看到了这一点-也在使用AWS的2.4.8 SDK。在AWSClientContext.m第54行中触发了错误。是否有运气解决此问题?
CharlesA 2013年

1
@YoonLee btw,刚刚使用以下答案之一解决了这一问题:“为目标功能打开了密钥链共享”
CharlesA 2016年

1
@CharlesA是的,那天我确实解决了。你是对的。似乎已打开“ KeyChain授权”解决了该问题。令人惊讶的是,此错误不会总是触发。无论如何,现在我将其打开。
李允(Yoon Lee)

25

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

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

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

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


确认此问题已在测试环境中修复。我必须将运行脚本添加到实际的测试目标上(例如,带有所有单元测试的脚本,而不是在设备上运行的构建目标)。还确认这只是设备上的问题,而不是模拟器上的问题。

2
当我这样做时,我得到“:找不到身份,命令/ bin / sh失败,退出代码为1”?猜猜我没有$ CODE_SIGN_IDENTITY。知道我该如何解决吗?
Daniel Coffman 2014年

1
@DanielCoffman,您必须转到目标设置,然后在“代码签名身份”中选择“ iOS开发人员”(或任何其他有效身份)。这可以解决构建错误,但是至少对我而言,不能解决钥匙串问题。我仍然收到-34018错误代码。
Marcin 2014年

3
谢谢Marcin。当我切换到xcode 6 beta时,我开始收到此错误。此线程中没有任何建议得到解决。还原为xcode 5和-34018不再发生。
Daniel Coffman 2014年

自从我使用XCode 6.3以来,我也第一次遇到此错误。
弗拉迪米尔·斯拉维克

13

经过检查的源代码。我注意到,钥匙串功能是通过在其自己的进程(与应用程序进程分开)中运行的安全守护程序访问的。

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

如有必要,可以通过XPC众所周知的启动命令来启动securityd。您可能可以检查该守护程序是否正在活动监视器应用程序中运行(如果在模拟器中运行,当然),并且其父进程已启动。

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

也许您可以考虑如何预启动守护程序。

抱歉,我没有说清楚。我希望它可以帮助您进一步展开调查。


2
仅当使用以下应用程序委托方法通过深层链接重新打开我的应用程序时,才会出现此问题:-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url。如果我只是启动该应用程序,则钥匙串编写有效,而如果我最小化和最大化该应用程序,则它仍然有效。只有当我重新打开深层链接时,才会出现此问题。我7 beta 4版本确实有在我的项目(在功能选项卡钥匙扣共享)配置MyApp.entitlements的Xcode
FranticRock

我的案例与Alex的案例相似,只有在应用深度链接时才会发生。否则运行正常。从另一个应用程序打开该应用程序时,某些上下文可能不正确。
CodeBrew

12

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

但是我还有另一个问题。我正在开发静态库,供其他示例应用程序使用。上面的解决方案适用于演示应用程序项目,但是当我尝试对静态库项目进行单元测试时,却出现了完全相同的错误。问题是我的静态库项目没有“功能”选项卡(因为它不是独立的应用程序)。

我已经尝试了JorgeDeCorte在此处发布的解决方案,并在测试目标中进行了代码签名,但是它对我不起作用。


8
并回到iOS 8 beta 3 :)
Mustafa 2014年

7
并返回iOS 9.0
Alex Stone

4
现在回到iOS 9.2 :-(
Vamos

4
返回iOS 10 beta 2
Pranjal Bikash Das

3
并回到iOS 10 beta 5
Pascal

6

从Xcode 启动应用程序时,请尝试禁用所有断点。您可以随后启用它们。

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


奇怪。似乎也为我解决了这个问题!每次我开始在模拟器上调试时,我都会遇到-34018 OSStatus。
2016年

4

我在运行7.1和8.0的模拟器上遇到了相同的问题。在进行一些挖掘时,我注意到Apple示例应用程序已为其目标功能打开了KeyChain Sharing。我为我的应用程序打开了它,结果创建了一个保留默认值的授权文件,现在不再出现-34018错误。这并不理想,但我现在将使用KeyChain共享选项。


4

在某些情况下,共同设计.xctest包并不像听起来那样容易。原则上,JorgeDeCorte的回答是正确的,即给定的短线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

4

我也为此感到痛苦,并且其他任何变通办法都没有成功。然后,我通过删除与我的应用程序相关的所有配置文件以及所有通配符配置文件来清理设备上的配置文件(这似乎很重要)。为此,请转到Xcode中的“设备”窗口,然后右键单击(已连接的)电话:

单击“显示配置文件”,然后删除相关的文件,尤其是团队配置文件:

包括带有星号的内容。重新安装该应用程序后,一切恢复正常。


这帮助我从Xcode运行应用程序并继续开发过程。
salabaha

构建AdHoc版本时,您可以检查使用了哪些PP。如果您看到任何XC:配置文件,请删除这些配置文件并刷新您的PP!
dogsgod

我可以看到这可能是一个因素。那里真是一团糟!做一些秋季清理工作
David

3

我已经解决了这个问题(我认为)。我的设备上有一个通配符配置配置文件,显示该配置文件没有有效的签名身份。我还为我的应用设置了有效的配置文件。当我删除通配符配置文件时,我不再遇到-34018错误。

我还确保目标构建设置的“代码签名”部分中列出的代码签名身份和配置文件与该应用程序的代码签名身份和配置文件相同(而不是通用的“ iPhone开发者”)。


与此类似为我修复了它。将项目级别的代码签名设置为“ iPhone Developer”进行调试,将“ iPhone Distribution”设置为Release。然后,我删除了主要目标上的替代,使它们显示相同。以前,保存在钥匙串中的失败率是100%。之后,保存在钥匙串中似乎是稳定的。
jowie 2015年

2

我正在-34018错误在我的应用(iOS 8.4),非常罕见。经过一番调查,我发现当应用程序过于频繁地从钥匙串中请求数据时,就会发生此问题。
例如,在我的情况下,是同时从不同的应用程序模块读取两个对一个特定密钥的请求。
为了解决这个问题,我刚刚在内存中添加了该值的缓存


1

我当时遇到了同样的问题,突然在运行有Xcode 6.2,iPhone 6,iOS 8.3的测试设备上运行。需要明确的是,这不是在运行Xcode测试时经历过,而是在我的设备上运行实际应用时经历的。在模拟器中一切正常,直到最近在应用程序本身上运行都非常好。

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

然后,我将可访问性级别从暂时更改kSecAttrAccessibleAfterFirstUnlockkSecAttrAccessibleAlwaysThisDeviceOnly,运行该应用程序,它可以正常工作并能够写入钥匙串。然后,我将其更改回kSecAttrAccessibleAfterFirstUnlock,问题似乎已经“永久”消失了。


1

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


1

我遇到过同样的问题。通过设置“钥匙串共享”修复了该问题。


1

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

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

遵循daidai的回答中的提示,

问题的某些实例是由不正确的应用程序签名引起的。您可以轻松地区分这种情况,因为该问题是100%可重现的。

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

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

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

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

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


0

在iOS 9中,我关闭了Address Sanitizer,它开始在设备上运行。


0

对我来说唯一有效的解决方案是先为指定的键存储nil,然后通过单独的操作存储新值。如果我尝试覆盖现有值,它将由于错误-34018而失败。但是,只要我先存储nil,那么更新后的值将立即成功存储。


0

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

对不起,它又回来了:(



0

什么对我有用

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

0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.