kSecAttrAccessibleAfterFirstUnlock即使在首次解锁iOS后也不允许访问

时间:2014-12-21 04:29:46

标签: ios keychain

所以我有一个旧的敏感访问密钥,当前具有kSecAttrAccessible WhenUnlocked的可访问性,我想将其更新为kSecAttrAccessibleAfterFirstUnlock。

我正在使用Lockbox并将其调用:

[Lockbox setString:accessKey forKey:self.accessKeyName accessibility:kSecAttrAccessibleAfterFirstUnlock];

反过来,这称之为:

-(BOOL)setObject:(NSString *)obj forKey:(NSString *)key accessibility:(CFTypeRef)accessibility
{
    OSStatus status;

    NSString *hierKey = [self _hierarchicalKey:key];

    // If the object is nil, delete the item
    if (!obj) {
        NSMutableDictionary *query = [self _query];
        [query setObject:hierKey forKey:(LOCKBOX_ID)kSecAttrService];
        status = SecItemDelete((LOCKBOX_DICTREF)query);
        return (status == errSecSuccess);
    }

    NSMutableDictionary *dict = [self _service];
    [dict setObject: hierKey forKey: (LOCKBOX_ID) kSecAttrService];
    [dict setObject: (LOCKBOX_ID)(accessibility) forKey: (LOCKBOX_ID) kSecAttrAccessible];
    [dict setObject: [obj dataUsingEncoding:NSUTF8StringEncoding] forKey: (LOCKBOX_ID) kSecValueData];

    status = SecItemAdd ((LOCKBOX_DICTREF) dict, NULL);
    if (status == errSecDuplicateItem) {
        NSMutableDictionary *query = [self _query];
        [query setObject:hierKey forKey:(LOCKBOX_ID)kSecAttrService];
        status = SecItemDelete((LOCKBOX_DICTREF)query);
        if (status == errSecSuccess)
            status = SecItemAdd((LOCKBOX_DICTREF) dict, NULL);
    }
    if (status != errSecSuccess)
        DLog(@"SecItemAdd failed for key %@: %d", hierKey, (int)status);

    return (status == errSecSuccess);
}

正如您在上面所看到的,如果存在重复,则Lockbox代码似乎尝试添加该项目。我在那里设置了一个断点,可以确认它确实有效。

但是,有时它仍会出现错误:

<Error>:  SecOSStatusWith error:[-25308] The operation couldn’t be completed. (OSStatus error -25308 - Remote error : The operation couldn‚Äôt be completed. (OSStatus error -25308 - ks_crypt: e00002e2 failed to unwrap item (class 6, bag: 0) Access to item attempted while keychain is locked.))

我不明白为什么我会这样 - 我已经解锁了我的手机,它应该工作正常。有什么想法吗?

我还应该补充一点,当应用程序在后台通过区域监控更新被终止并恢复时,我需要访问它。

1 个答案:

答案 0 :(得分:5)

我必须在新密钥之前清除旧密钥。您可以这样做,或者您可以使用新的kSecAccessibility值创建具有不同名称的新密钥。