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

Posted

技术标签:

【中文标题】SecItemAdd 和 SecItemCopyMatching 返回错误代码 -34018 (errSecMissingEntitlement)【英文标题】:SecItemAdd and SecItemCopyMatching returns error code -34018 (errSecMissingEntitlement) 【发布时间】:2013-12-19 02:28:28 【问题描述】:

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

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

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

我正在使用SSKeychain 库与钥匙串进行交互。这是sn-p。

#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 的应用程序中似乎还可以。它只发生在开发版应用程序中。 我有应用商店版本的崩溃分析,不幸的是,它似乎也发生在应用商店中,尽管频率低于开发:/ 我正在考虑放弃钥匙串,因为存储在钥匙串中的数据可能会像这样随机丢失,这对应用程序来说几乎是一个致命错误。 我们也看到了这个间歇性问题。当我们从 secItemCopyMatching 获得意外的 rc(包括 -34018 情况)时,我们会引发异常。我们尝试(不情愿地)添加一种机制,一旦我们从钥匙串中获得所需的值,我们将其缓存在应用程序内存中,然后从那里提供它而无需钥匙串访问。但是现在我们看到很少有这样的情况,首先获得它的一个钥匙串访问会失败,并显示 -34018。有没有人尝试在 -34018 之后重试操作? 【参考方案1】:

iOS 10 / XCode 8 修复:

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

这里有一个答案,来自 Apple:

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

像往常一样,我们不能承诺发布时间框架,但这有 影响了许多开发人员,我们真的很想解决这个问题。

之前我建议在 应用程序:didFinishLaunchingWithOptions 和 applicationDidBecomeActive:在访问钥匙串之前作为 解决方法。但是,这实际上似乎没有帮助。这意味着 目前除了重新启动之外没有已知的解决方法 应用程序。

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

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

更新

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

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

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

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

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

【讨论】:

iOS 9.2、iPhone 5S 上问题依旧。 看起来 iOS 9.3 应该根据您链接的线程中的 latest response from Apple 解决此问题。 @daidai,你能用这个新信息更新你的答案吗? @YoonLee 在 iOS10 中也看到了这一点——也使用 AWS 的 2.4.8 SDK。 AWSClientContext.m 第 54 行中触发了错误。解决这个问题有运气吗? @YoonLee 顺便说一句,刚刚使用以下答案之一解决了这个问题:'KeyChain Sharing 打开了目标功能' @CharlesA 是的,那天我确实解决了。你说的对。似乎是“KeyChain Entitlement 打开”解决了这个问题。令人惊讶的是,这个错误并不总是触发。无论如何,现在我正在打开它。【参考方案2】:

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

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

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

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

【讨论】:

确认这已在测试环境中修复它。我必须将运行脚本添加到实际的测试目标(例如带有所有单元测试的那些,而不是在设备上运行的构建目标)。还确认这只是设备上的问题,而不是模拟器上的问题。 当我这样做时,我得到“:找不到身份命令 /bin/sh 失败,退出代码为 1”?猜我没有$CODE_SIGN_IDENTITY。知道如何解决这个问题吗? @DanielCoffman,您必须转到目标设置并在代码签名身份中选择“iOS 开发人员”(或任何其他有效身份)。这修复了构建错误,但至少对我来说它不能解决钥匙串问题。我仍然得到 -34018 错误代码。 谢谢马尔辛。当我切换到 xcode 6 beta 时,我开始收到此错误。没有解决此线程中的建议。恢复到 xcode 5 和 -34018 不再出现。 自从我使用 XCode 6.3 以来,我第一次遇到这个错误。【参考方案3】:

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

您的应用和受保护的进程通过一种称为XPC 的技术一起“对话”。

如有必要,securityd 将通过 XPC 众所周知的 launchd 命令启动。您可能可以检查守护程序是否在 Activity Monitor App 中运行(当然如果在模拟器中运行)并且它的父进程已启动。

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

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

我很抱歉没有更准确。我希望它可以帮助您进一步调查。

【讨论】:

只有当我的应用程序通过使用以下应用程序委托方法的深层链接重新打开时才会出现此问题:- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url。如果我只是启动应用程序,钥匙串编写工作,如果我最小化和最大化应用程序,它仍然有效。只有当我使用深层链接重新打开时才会出现此问题。我确实在我的项目中配置了 MyApp.entitlements(功能选项卡中的钥匙串共享)Xcode 7 beta 4。 我的情况与 Alex 的情况类似,只有当应用程序被深度链接时才会发生这种情况。否则它运行良好。从另一个应用程序打开应用程序时,可能某些上下文不正确。【参考方案4】:

在使用 iOS 8 SDK 在 Xcode 6 beta 中构建和运行我的代码后,我观察到了类似的行为(它与 Xcode 5 / iOS 7 一起正常工作)。在 Xcode 6 中,在 iOS 模拟器中 SecItemCopyMatching 总是返回 -34018。打开 Capabilities 标签中的“Keychain Sharing”后,它开始工作了。

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

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

【讨论】:

在 iOS 8 beta 2 中修复。 回到 iOS 8 beta 3 :) 现在回到 iOS 9.2 :-( 返回 iOS 10 beta 2 回到 iOS 10 beta 5【参考方案5】:

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

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

【讨论】:

奇怪。似乎也为我解决了这个问题!每次我开始在模拟器上调试时,我都会遇到 -34018 OSStatus。【参考方案6】:

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

【讨论】:

【参考方案7】:

在某些情况下,对 .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】:

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

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

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

【讨论】:

这帮助我从 Xcode 运行应用程序并继续开发过程。 在构建 AdHoc 版本时,您可以检查使用了哪些 PP。如果您看到任何 XC: 配置文件,请删除这些配置文件并刷新您的 PP! 我知道这可能是一个因素。里面乱七八糟的!!做一些秋季大扫除【参考方案9】:

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

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

【讨论】:

与此类似,为我修复了它。将项目级代码签名设置为“iPhone Developer”以进行调试,将“iPhone Distribution”设置为发布。然后我删除了主要目标上的覆盖,因此它们显示相同。以前,保存在钥匙串中的失败率是 100%。之后,保存在钥匙串中似乎很稳定。【参考方案10】:

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

【讨论】:

【参考方案11】:

我在使用 Xcode 6.2、iPhone 6、iOS 8.3 的测试设备上运行时遇到了同样的问题,出乎意料。需要明确的是,这不是在运行 Xcode 测试时遇到的,而是在我的设备上运行实际应用程序时遇到的。在模拟器中它很好,并且在应用程序本身上运行它直到最近都很好。

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

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

【讨论】:

【参考方案12】:

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

【讨论】:

【参考方案13】:

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

【讨论】:

【参考方案14】:

(这不是对 OP 问题的直接回答,但可能对其他人有所帮助)

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

按照daidai's answer 的这个提示,

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

我们发现,Provisioning Profile 在目标的 Signing 部分中不知何故被设置为 None。

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

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

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

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

【讨论】:

【参考方案15】:

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

【讨论】:

【参考方案16】:

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

【讨论】:

【参考方案17】:

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

抱歉又回来了:(

【讨论】:

【参考方案18】:

在您的项目功能中开启钥匙串共享,它应该可以解决问题。

【讨论】:

【参考方案19】:

什么对我有用

开启钥匙串共享。 尽量少使用keychain,将数据缓存在内存、UserPreferences、磁盘等中。 如果这些操作失败,请重试多次钥匙串 CRUD 操作。 使用 DispatchQueue.sync 存储/删除/更新数据。

【讨论】:

【参考方案20】:

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

【讨论】:

以上是关于SecItemAdd 和 SecItemCopyMatching 返回错误代码 -34018 (errSecMissingEntitlement)的主要内容,如果未能解决你的问题,请参考以下文章

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

kSecUseAuthenticationUISkip 使用方法

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

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

& 和 && 区别和联系,| 和 || 区别和联系

第三十一节:扫盲并发和并行同步和异步进程和线程阻塞和非阻塞响应和吞吐等