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

有时,当我在 Xcode 的设备上运行应用程序时,我会尝试访问密钥链,但由于错误而失败。这与任何已记录的密钥链错误代码都不匹配,无法一致地重现。(大约30% 的情况下会发生,我不清楚为什么会发生)。完全缺乏文档使得调试这个问题非常困难。知道是什么导致了这一切,以及如何解决吗?我使用 Xcode 5并在设备上运行 iOS 7.0.4。

There is an open issue about this here: 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

大多数情况下都没问题。有时我会遇到断言失败,无法写入或读取密钥链,从而导致关键断言失败。

40430 次浏览

在检查了 < strong > 源代码 之后。我注意到,keychain 特性是通过一个安全守护进程访问的,该守护进程在自己的进程中运行(与应用程序进程分离)。

您的应用程序和安全进程通过一种名为 XPC 的技术进行“对话”。

If necessary, the securityd is launched via the well-known launchd command by XPC. You can probably check that the daemon is running in the Activity Monitor App (if running in Simulator of course) and that its parent process is launchd.

我的猜测是,由于任何未知的原因,安全守护进程可能无法启动或执行得太慢,并且在您尝试使用它时还没有准备好。

也许你可以想想如何提前启动守护进程。

I apologize for not being more precise. I hope it could help you to go a bite further in your investigations.

基本上,您必须通过在测试目标中添加以下运行脚本来协同设计.xcttest 文件夹。

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

I got a lot of -34018 errors when testing my keychain on the device and this managed to fix it.

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

I just had the same issue on the simulator running 7.1 & 8.0. While doing some digging, I noticed that the Apple sample app had KeyChain Sharing turned on for its target capabilities. I turned it on for my app which resulted in creating an entitlement file that I left with the default values and now I am not getting anymore -34018 errors. This is not ideal but I will live the KeyChain sharing option for now.

在使用 iOS8SDK 在 Xcode 6 beta 中构建和运行我的代码之后,我观察到了类似的行为(它在 Xcode 5/iOS7中工作正常)。在 Xcode 6中,iOS Simulator 中的 SecItemCopymatch 总是返回 -34018。它开始工作后,打开“钥匙链共享”在能力标签。

不过我还有一个问题。我正在开发静态库,这是演示应用程序所使用的。上面的解决方案适用于 Demo 应用程序项目,但是当我尝试对静态库项目进行单元测试时,出现了完全相同的错误。问题是我的静态库项目没有“能力”选项卡(因为它不是绿色软体)。

I’ve tried the solution posted here by JorgeDeCorte, with codesigning in the test target, but it doesn’t work for me.

共同设计一个。在某些情况下,xctest bundle 并不像听起来那么简单。主要 JorgeDeCorte 是正确的与他的 回答,给定的短线作为一个 Run Script是足够的大多数开发者。

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

But when you have multiple certificates in your keychain this will fail with the following line

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

即使有多个证书,也可以通过这个简短的脚本获得正确的证书。当然,这并不理想,但据我所知,您没有机会获得 Xcode 找到并用于签名您的。应用程序。

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

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

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

我也遇到过同样的问题,在 Xcode 6.2,iPhone 6,iOS 8.3的测试设备上运行。需要说明的是,这不是在运行 Xcode 测试时遇到的问题,而是在我的设备上运行实际的应用程序时遇到的问题。在模拟器中它很好,并且在应用程序本身上运行它一直非常好,直到最近。

I tried all of the suggestions I could find here, such as removing the provisioning profiles on my device (I removed ALL of them), temporarily enabling the Keychain Sharing capability in my project (even though we don't really need that), making sure my development account in Xcode was totally refreshed with all of the certificates and provisioning profiles, etc. Nothing helped.

然后,我暂时改变了可访问级别从 kSecAttrAccessibleAfterFirstUnlockkSecAttrAccessibleAlwaysThisDeviceOnly,运行应用程序,它工作良好,并能够写到钥匙链。然后我把它改回 kSecAttrAccessibleAfterFirstUnlock,这个问题似乎已经“永久”消失了

IOS 10/XCode 8修正:

添加键链权限,转到项目 设置-> 功能-> 钥匙链共享-> 添加钥匙链组 + 打开

苹果的回答是:

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

As usual, we can't commit to a release timeframe, but this has affected many developers and we really want to get this resolved.

早些时候我建议在 application:didFinishLaunchingWithOptions and ApplicationDidBecomeActive: 在将密钥链作为 但是,这似乎并没有实际帮助。这意味着 目前除了重新发射,没有其他已知的解决方案 应用程序。

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

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

更新

好了,这是最新消息。
This is a complex problem with multiple 可能的原因:

  • 问题的某些实例是由不正确引起的 app signing. You can easily distinguish this case because the problem 是100% 可复制的。
  • 问题的某些实例是由 IOS 如何支持应用程序开发(r. 23,991,853) 这是复杂的事实,另一个错误在操作系统(r。 23,770,418)掩盖了其影响,这意味着问题只是突然出现 我们相信这些问题 是在 iOS 9.3中解决的。
  • 我们怀疑可能还有更多的原因 这个问题。

因此,如果您在用户设备上看到这个问题(1 还没有被 Xcode 访问过)运行 iOS 9.3或更高版本的, 请提交有关它的错误报告。尝试包括该设备 系统日志的错误报告(我知道这可能是棘手的时候 处理客户设备; 一种选择是要求客户 安装 Apple Configurator,让他们查看系统日志) if you do file a bug, please post your bug number, just for the 记录。

我代表苹果公司感谢大家 我们正致力协助追查这个相当可怕的问题 好好享受吧

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

我的应用程序(iOS 8.4)很少出现 -34018错误。经过一些调查,我发现这个问题发生时,应用程序请求数据从键链 太频繁了
例如,在我的情况下,是两个读请求同时从不同的应用程序模块中读取一个特定的键。
为了解决这个问题,我刚刚在内存中添加了这个值的缓存

我也被这个咬了一口,其他的变通方法都没有成功。 I then cleaned up my provisioning profiles on the devices itself by deleting all of them related to my app as well as all the wildcard profiles (this seems to be the point). 要做到这一点,进入 Xcode 的“设备”窗口,右键单击你的(已连接)手机:

点击“显示供应配置文件”并删除相关配置文件,特别是团队配置文件:

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

在 iOS9中,我关闭了地址消毒器,它开始在设备上工作。

The only solution that worked for me was first storing nil for the specified key, and then storing my new value with a separate operation. It would fail due to error -34018 if I attempted to overwrite the existing value. But as long as I stored nil first, then the updated value would be stored successfully immediately afterwards.

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

对不起,它又回来了: (

试试 Xcode 的 启动应用程序时禁用所有断点。 之后可以启用它们。

(以上方法对我都不管用)

在 Xcode 8 Beta 3上被这个 bug 咬了一口。打开钥匙链共享似乎是唯一的解决方案。

我也有同样的问题。通过设置钥匙链共享修复了它。

(this is not a direct answer to the OP's question, but might help others)

Started getting the keychain error -34018 consistently in simulator after updating Xcode from version 7.3.1 to 8.0.

根据 代代的回答的消息,

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

发现在目标的签名部分中,供应配置文件以某种方式被设置为 Nothing。

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

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

按“修复问题”修复推送通知问题后,解决了键链错误。

对于这个特定的目标,“钥匙链共享”权限已经在以前的某个时间被打开。到目前为止,关闭它并没有导致键链错误再次出现,因此不清楚在这种情况下是否有必要。

在您的项目的能力中打开 Keychain share ,它应该可以解决这个问题。 enter image description here

对我有用的东西

  • 打开钥匙链共享。
  • 尽可能少地使用密钥链,并将数据缓存到内存、 UserPreferences、磁盘等中。
  • 如果这些操作失败,请多次重试密钥链 CRUD 操作。
  • 使用 DispatchQueue.sync 存储/删除/更新数据。

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