49

我正在使用SecItemCopyMatching访问 iOS 钥匙串。-34018从后台重新启动应用程序后,我大约有一百分之一得到结果代码。该文档指出:

为钥匙串服务分配的错误空间是不连续的:–25240 到 –25279 和 –25290 到 –25329。Keychain Item Services 也可能返回 noErr (0) 或 paramErr (–50) 或 CSSM 结果代码

所以这似乎-34018是一个'CSSM结果代码'。我已按照建议的链接进行操作,但找不到结果代码。

-34018结果代码是什么?如何获得更可靠的钥匙串访问?

- (NSData *)getKeychainData:(NSString *)key
{
    NSDictionary *query = @{
        (__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
        (__bridge id)kSecAttrService:SEC_ATTR_SERVICE,
        (__bridge id)kSecAttrAccount:key,
        (__bridge id)kSecReturnData:@YES
    };

    CFDataRef result = nil;

    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);

    if(status == errSecItemNotFound) {
        return nil;
    }

    if(status == noErr) {
        return CFBridgingRelease(result);
    } else {
        [self logError:[NSString stringWithFormat:@"SecItemCopyMatching status %d", (int)status] :nil];
        return nil;
    }
}
4

4 回答 4

21

我一直在研究同样的错误。

它的要点是苹果使用安全服务来与钥匙串通信,在极少数情况下,当用户的设备内存不足时,崩溃并剥夺应用程序与钥匙串通信的能力,这会导致可怕的 - 34018。

这不仅仅像某些人声称的那样仅在通过 Xcode 运行时发生。

这是一位 Apple 员工从 Apple 开发者论坛获取的有关该问题的最新数据:

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

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

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

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

来自另一位 Apple 员工:

  • 钥匙串工程非常清楚这个问题的重要性。
  • 主要问题是在苹果公司重现失败。
  • 我们现在能够做到这一点(很大程度上要感谢你们在提交和跟进错误报告方面所做的工作)。

来自2016 年 3 月 22 日的另一位 Apple 员工:

好的,这是最新的。这是一个具有多种可能原因的复杂问题: 某些问题实例是由不正确的应用签名引起的。您可以轻松区分这种情况,因为问题是 100% 可重现的。该问题的某些实例是由 iOS 支持应用程序开发的错误引起的 (r. 23,991,853)。由于操作系统中的另一个错误 (r. 23,770,418) 掩盖了它的影响,这使得调试变得复杂,这意味着该问题仅在设备处于内存压力下时才会出现。我们相信这些问题在 iOS 9.3 中得到了解决。我们怀疑这个问题可能还有更多的原因。因此,如果您在运行 iOS 9.3 或更高版本的用户设备(Xcode 尚未与之交谈的设备)上发现此问题,请提交有关它的错误报告。尝试在您的错误报告中包含设备系统日志(我意识到在处理客户设备时可能会很棘手;一种选择是要求客户安装 Apple Configurator,以便他们查看系统日志)。如果您确实提交了错误,请发布您的错误编号,以供记录。我代表 Apple 感谢大家为帮助追查这个相当可怕的问题所做的努力。分享和享受

不幸的是,没有已知的解决方法,并且该问题在 9.3.2 Beta 1 (13F51a) 中仍未解决

于 2015-11-19T18:28:23.087 回答
20

经过一番研究,我发现了这个: http: //opensource.apple.com/source/Security/Security-55471/sec/Security/SecBasePriv.h

-34018也是如此errSecMissingEntitlement,评论说

Internal error when a required entitlement isn't present.

您在运行单元测试时是否遇到此错误?如果是这样,这可能会有所帮助:https ://stackoverflow.com/a/22305193/171933

github上的这个问题说它似乎只在从Xcode调试时发生:https ://github.com/soffes/sskeychain/issues/97 (另见https://stackoverflow.com/a/28256591/171933

希望其中一些会有所帮助!

于 2015-05-01T13:20:46.240 回答
4

这段代码对我有用:

static const UInt8 kKeychainItemIdentifier[] = "com.apple.dts.KeychainUI\0";

- (NSData *)getKeychainData:(NSString *)key
{
    NSData *keychainItemID = [NSData dataWithBytes:kKeychainItemIdentifier length:strlen((const char *)kKeychainItemIdentifier)];

    NSDictionary *query = @{
        (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
        (__bridge id)kSecAttrService: SEC_ATTR_SERVICE,
        (__bridge id)kSecAttrAccount: key,
        (__bridge id)kSecReturnData: (__bridge id)kCFBooleanTrue,
        (__bridge id)kSecAttrGeneric: keychainItemID
    };

    CFDataRef result = NULL;

    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);

    if(status == errSecItemNotFound) {
        return nil;
    }

    if(status == noErr) {
        return CFBridgingRelease(result);
    } else {
        [self logError:[NSString stringWithFormat:@"SecItemCopyMatching status %d", (int)status] :nil];
        return nil;
    }
}

与 OP 代码的主要区别是在查询中添加了通用属性。Keychain Item Identifier 是苹果的默认值。这背后的原因是为了区分可能的不同钥匙串项目。这是使钥匙串项目访问更可靠的一种方法。基本上,换句话说,这可以确保您访问苹果的默认钥匙串。

于 2015-05-08T03:31:24.340 回答
0

在尝试了堆栈溢出中的许多修复后,事情仍然对我不起作用。

有效的是在 Xcode 中切换钥匙串共享功能。构建并运行,它立即工作。

在此处输入图像描述

于 2016-10-06T02:09:24.863 回答