禁用和重新启用Touch ID时出现钥匙串错误-25300(errSecItemNotFound) [英] Keychain error -25300 (errSecItemNotFound) when disabling and re-enabling Touch ID

查看:116
本文介绍了禁用和重新启用Touch ID时出现钥匙串错误-25300(errSecItemNotFound)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将密码保存到带有Touch ID标志的钥匙串中:

I save the password to keychain with Touch ID flags:

+ (void)setPasscode:(NSString *)passcode
{
    CFErrorRef error = NULL;
    SecAccessControlRef sacObject;

    sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
                                                    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
                                                    kSecAccessControlUserPresence, &error);


    if(sacObject == NULL || error != NULL)
    {
        DLog(@"can't create sacObject: %@", error);
        return;
    }

    NSDictionary *attributes = @{
                                 (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                                 (__bridge id)kSecAttrService: kKeychainServiceName,
                                 (__bridge id)kSecValueData: [passcode dataUsingEncoding:NSUTF8StringEncoding],
                                 (__bridge id)kSecUseNoAuthenticationUI: @YES,
                                 (__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacObject
                                 };

    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        SecItemAdd((__bridge CFDictionaryRef)attributes, nil);
    });
}

并检索它:

+ (void)getCurrentPasscodeWithSuccess:(void (^)(NSString *))success failure:(void (^)(OSStatus))failure
{
    NSDictionary *query = @{
                            (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                            (__bridge id)kSecAttrService: kKeychainServiceName,
                            (__bridge id)kSecReturnData: @YES,
                            (__bridge id)kSecUseOperationPrompt: kOperationPrompt
                            };

    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        CFTypeRef dataTypeRef = NULL;

        OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)(query), &dataTypeRef);
        if (status == errSecSuccess)
        {
            if (success) {
                NSData *resultData = ( __bridge_transfer NSData *)dataTypeRef;
                NSString *result = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
                success(result);
            }
        } else {
            if (failure) {
                failure(status);
            }
        }
    });
}

这很好.但是,如果禁用Touch ID,然后在设备上重新启用它,SecItemCopyMatching将返回OSStatus -25300(errSecItemNotFound). 问题在于该项目仍然存在(我认为).因为当我尝试tio访问时,出现Touch ID提示.

This works fine. But if you disable Touch ID, and re-enable it on device, SecItemCopyMatching returns OSStatus -25300 (errSecItemNotFound). Problem is that item still exists there (I think). Because when I try tio access it, Touch ID prompt comes up.

我尝试通过以下方法检查项目是否存在:

I tried to check if item exists with the following method:

+ (void)checkIfPasscodeExistsInKeychainWithCompletion:(void (^)(BOOL))completion
{
    NSDictionary *query = @{

                            (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                            (__bridge id)kSecAttrService: kKeychainServiceName,
                            };

    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        CFTypeRef dataTypeRef = NULL;

        OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)(query), &dataTypeRef);
        BOOL exists = status != errSecItemNotFound;

        if (completion) {
            completion(exists);
        }
    });
}

这会触发Touch ID提示,然后返回提供触摸时不存在的错误.

And this triggers the Touch ID prompt, and then returns error that it doesn't exist when touch is provided.

但是,如果我删除(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword行,则会得到它在钥匙串中的状态.

But if I remove (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword line, I get the status that it exists in keychain.

推荐答案

您正在使用 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly 作为项目的可访问性常量.这意味着只有在设备上设置了密码并添加了TouchID的情况下,才可以添加该项目.如果您在将商品保存到钥匙串中之后删除了设备密码(或者您的情况下为TouchID),则该商品将不再可用.

You are using kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly as the Accessiblity constant for your item. This means that the item can only be added when there is a passcode set on the device, with the addition of the TouchID. If you remove your device passcode (or in your case TouchID) after your item is saved in the keychain, this item will no longer be available.

即使您重新添加设备密码(或TouchID),该项目也不再可用.您必须创建同一项目的重复副本.

Even if you add the device passcode (or TouchID) back, this item is no longer available. You have to create a duplicate copy of the same item.

有关kSecAttrAccessible常量的更多信息,请参阅文档:

For more information on kSecAttrAccessible constant, refer the docs: Keychain Item Accessibility Constants.

有关整个过程如何工作的信息,请参考 Apple的安全白皮书

For information on how the whole process works, refer Apple's security whitepaper

这篇关于禁用和重新启用Touch ID时出现钥匙串错误-25300(errSecItemNotFound)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆