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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20344255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:35:59  来源:igfitidea点击:

SecItemAdd and SecItemCopyMatching returns error code -34018 (errSecMissingEntitlement)

ioscocoakeychainsskeychain

提问by Tony

Sometimes when I run an application on device from Xcode I would try to access the keychain but fail due to error -34018. This doesn't match any of the documented keychain error codes and can't be consistently reproduced. (happens maybe 30% of the time, and it's not clear to me why it happens). What makes debugging this problem very difficult is the total lack of documentation. Any idea what causes this and how to fix it? I'm using Xcode 5 and running iOS 7.0.4 on device.

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

There is an open issue about this here: https://github.com/soffes/sskeychain/issues/52

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

EDIT: Adding keychain access code per request

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

I'm using the SSKeychainlibrary for interfacing with keychain. Here's the snippet.

我正在使用该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

Vast majority of the time it's just fine. Sometimes I'll hit the assertion failures where I'm unable to either write to or read from keychain, causing critical assertion failure.

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

回答by daidai

iOS 10 / XCode 8 Fix:

Add KeyChain Entitlement, Go to project settings->Capabilities->Keychain Sharing->Add Keychain Groups+Turn On

iOS 10 / XCode 8 修复:

添加钥匙串授权,进入项目设置->功能->钥匙串共享->添加钥匙串组+开启

An answer here, from Apple:

来自 Apple 的回答:

UPDATE: We have finally been able to reproduce the -34018 error on iOS 8.3. This is the first step in identifying the root cause and then coming up with a fix.

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

Earlier I suggested adding a small delay in application:didFinishLaunchingWithOptions and applicationDidBecomeActive: before accessing the keychain as a workaround. However, that doesn't actually appear to help. That means that there's no known workaround at this time other than relaunching the app.

The issue appears to be related to memory pressure, so perhaps being more aggressive in handling memory warnings may alleviate the problem

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

像往常一样,我们无法承诺发布时间表,但这已经影响了许多开发人员,我们真的很想解决这个问题。

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

该问题似乎与内存压力有关,因此可能更积极地处理内存警告可能会缓解该问题

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

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

UPDATE

更新

OK, here's the latest.
This is a complex problem with multiple possible causes:

  • Some instances of the problem are caused by incorrect app signing. You can easily distinguish this case because the problem is 100% reproducible.
  • Some instances of the problem are caused by a bug in how iOS supports app development (r. 23,991,853). Debugging this was complicated by the fact that another bug in the OS (r. 23,770,418) masked its effect, meaning the problem only cropped up when the device was under memory pressure. We believe these problems were resolved in iOS 9.3.
  • We suspect that there may be yet more causes of this problem.

So, if you see this problem on a user device (one that hasn't been talked to by Xcode) that's running iOS 9.3 or later, please do file a bug report about it. Try to include the device system log in your bug report (I realise that can be tricky when dealing with customer devices; one option is to ask the customer to install Apple Configurator, which lets them view the system log). And if you do file a bug, please post your bug number, just for the record.

On behalf of Apple I'd like to thank everyone for their efforts in helping to track down this rather horrid issue. Share and Enjoy

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

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

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

回答by JorgeDeCorte

Basically you have to codesign your .xcttest folder by adding the following as a run script in your test target.

基本上,您必须通过在测试目标中添加以下作为运行脚本来对 .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.

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

If the problem does not exist in your test target this is probably not the solution.

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

回答by Vincent Zgueb

After inspecting the source code. I have noticed that the keychain features are accessed through a security daemon that runs in its own process (separated from the app process).

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

Your app and the securityd process 'talk' together through a technology called XPC.

您的应用程序和安全进程通过一种称为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.

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

My guess here is that it is possible that for any unknown reason the security daemon fails to start or do it too slowly and is not ready when you try to use it.

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

Maybe you could think on how to pre-launch the daemon.

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

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

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

回答by Marcin

I'm observing similar behavior after building and running my code in Xcode 6 beta with iOS 8 SDK (it's working correctly with Xcode 5 / iOS 7). In Xcode 6, in iOS Simulator SecItemCopyMatching always returns -34018. It started working after turning on the “Keychain Sharing” in Capabilities tab.

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

However I have another issue. I'm developing static library, that is used by (among others) Demo application. The above solution works for Demo application project, but when I try to unit test my static library project, I have exactly the same error. And the problem is that my static library project doesn't have the Capabilities tab (as it's not the standalone application).

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

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

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

回答by HeTzi

Try disabling all breakpoints when launching the appfrom Xcode. You can enable them afterwards.

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

(None of the above workarounds worked for me)

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

回答by k1th

I got bitten by this, too and had no success with any of the other workarounds. 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). To do this, go to the "Devices" Window in Xcode and right-click your (connected) phone:

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

Click on "Show provisioning profiles" and delete the related ones, and especially the team profiles:

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

including the ones with the asterisk. After reinstallation the app, everything went back to normal.

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

回答by Laurent

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.

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

回答by Patrik

Codesigning a .xctest bundle isn't as easy as it sounds in some cases. Principally JorgeDeCorte is right with his answerthat the given short line as a Run Scriptis enough for most of the devs.

在某些情况下,编码 .xctest 包并不像听起来那么容易。主要 JorgeDeCorte 的回答是正确的,即给定的短线 aRun 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)"

A solution to get the right certificate even with multiple ones is this short script. For sure this is not ideal, but as of my knowledge you have no chance to get the certificate that Xcode found and uses for signing your .app.

即使有多个证书也能获得正确证书的解决方案是这个简短的脚本。当然这并不理想,但据我所知,您没有机会获得 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  }'`

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

回答by Dave Hirsch

I have fixed this problem (I think). I had a wildcard provisioning profile on my device that showed it did not have a valid signing identity. I also had a provisioning profile for my app that was valid. When I deleted the wildcard profile, I stopped getting the -34018 errors.

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

I also made sure that the code signing identity and provisioning profile listed in the Code Signing section of the Build Settings of the target were identical to the one for the app (not the generic "iPhone Developer" one)

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

回答by somedev

I was getting -34018error in my app (iOS 8.4) very rarely. After some investigation I've found that this issue occurs when the app requests data from keychain too often.
For example, in my situation it was two read requests for one specific key at the same time from different application modules.
To fix that I've just added caching this value in memory

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