117

有时,当我从 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

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

4

20 回答 20

47

iOS 10 / XCode 8 修复:

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

来自Apple的答案:

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

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

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

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

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

更新

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

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

于 2015-07-15T04:50:15.733 回答
27

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

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

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

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

于 2014-03-10T16:02:14.230 回答
13

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

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

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

于 2014-06-09T12:38:16.830 回答
13

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

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

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

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

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

我很抱歉没有更准确。我希望它可以帮助您在调查中走得更远。

于 2014-01-24T21:38:30.147 回答
6

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

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

于 2016-03-24T11:56:26.750 回答
4

在某些情况下,对 .xctest 包进行代码设计并不像听起来那么容易。基本上,JorgeDeCorte 的回答是正确的,即给定的短线作为 aRun 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
于 2014-07-24T09:19:26.370 回答
4

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

于 2014-06-08T07:16:22.247 回答
4

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

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

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

于 2015-10-12T16:30:22.020 回答
3

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

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

于 2014-08-06T00:30:28.297 回答
2

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

于 2015-09-16T06:29:56.827 回答
1

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

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

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

于 2015-06-22T18:37:54.283 回答
1

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

于 2016-08-01T06:53:57.363 回答
1

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

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

按照daidai的回答中的这个提示,

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

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

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

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

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

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

于 2016-09-14T22:06:40.383 回答
1

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

于 2016-08-04T19:44:56.387 回答
0

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

于 2019-07-24T15:12:38.157 回答
0

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

于 2015-10-14T19:37:10.797 回答
0

在您的项目功能中打开钥匙串共享,它应该可以解决问题。 在此处输入图像描述

于 2016-12-08T13:08:23.977 回答
0

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

于 2015-10-24T01:53:36.777 回答
0

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

对不起,它又回来了:(

于 2016-03-07T13:10:48.430 回答
0

什么对我有用

  • 打开钥匙串共享。
  • 尽量少用keychain,把数据缓存在内存、UserPreferences、磁盘等。
  • 如果这些操作失败,请重试多次钥匙串 CRUD 操作。
  • 使用 DispatchQueue.sync 存储/删除/更新数据。
于 2018-09-19T11:00:20.250 回答