SecItemAdd():errSecParam结果当尝试使用kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly

时间:2016-01-20 06:30:12

标签: ios keychain touch-id

最近的堆栈溢出有用的光明之光,

SecItemAdd()的钥匙串条目中使用 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly 属性时,还需要包含哪些其他属性?我的理解是 kSecAttrAccessControl kSecUseAuthenticationUI 是合适的,因此使用SecAccessControlRef实例和@(BOOL)。然而,这对我不起作用。

我试图在两个钥匙串条目中保存两个词典。

一个是成功的,另一个是失败的, 成功的那个使用 kSecAttrAccessibleAfterFirstUnlock 来获取可访问性。 失败的那个使用 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly ,并且失败的状态为errSecParam(-50) - 表明我在传递给SecItemAdd()时使用的参数不正确。

在成功的钥匙串条目中,字典中有5个键/值对传递给SecItemAdd()。

keychainQuery __NSDictionaryM *  5 key/value pairs
[0] @"svce" : @"session"
[1] @"acct" : @"com.xxx.yyy”
[2] @"v_Data" : 490 bytes
[3] @"class" : @"genp"
[4] @"pdmn" : @"ck"

@“pdmn”的@“ck”值对应于kSecAttrAccessibleAfterFirstUnlock辅助功能属性。 钥匙串项目已添加,并且可以检索并成功从中读取数据。

在不成功的钥匙串条目中,字典中有7个键/值对传递给SecItemAdd()。

keychainQuery __NSDictionaryM *  7 key/value pairs
[0] @"svce" : @"credentials"
[1] @"acct" : @"com.xxx.yyy”
[2] @"v_Data" : 370 bytes
[3] @"class" : @"genp"
[4] @"pdmn" : @"akpu"
[5] @"accc" : (no summary)
[6] @"u_AuthUI" : @"1"

@“pdmn”的@“akpu”值对应于kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly可访问性属性。 对于这个字典,还使用SecAccessControlRef实例和@(YES)指定了kSecAttrAccessControl和kSecUseAuthenticationUI。

以下是基本查询的创建方式:

+ (NSMutableDictionary *)getKeychainQuery
{
    NSMutableDictionary *queryDict = [NSMutableDictionary dictionary];

    queryDict[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword;
    queryDict[(__bridge id)kSecAttrService] = [self service];
    queryDict[(__bridge id)kSecAttrAccount] = [self account];

    if( [self userPresence] )
    {
        CFErrorRef error = NULL;
        SecAccessControlRef sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
                                                                            [self accessibility],
                                                                            kSecAccessControlUserPresence, &error);

        if (error == NULL || sacObject != NULL)
        {
            queryDict[(__bridge id)kSecAttrAccessControl] = (__bridge_transfer id)sacObject;
            queryDict[(__bridge id)kSecUseAuthenticationUI] = @YES;
        }
    }

    return queryDict;
}

以下是用法:

+ (void)saveToKeychain:(XGKeychainItem *)keychainItem
{
    NSMutableDictionary *keychainQuery = [self getKeychainQuery];
    keychainQuery[(__bridge id)kSecAttrAccessible] = (__bridge id)[self accessibility];

    NSData *keychainData = [NSKeyedArchiver archivedDataWithRootObject:keychainItem];
    keychainQuery[(__bridge id)kSecValueData] = keychainData;

    OSStatus addStatus = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
    NSLog(@"ADD STATUS: %d for service - %@", (int)addStatus, [self service]);
}

如果在将问题字典传递给SecItemAdd()之前,我删除了第一个字典中没有的两个属性,并将可访问性设置为与第一个字符匹配,则成功添加了keychain项。

所以,似乎我使用kSecUseAuthenticationUI,kSecAttrAccessControl和/或我的SecAccessControlRef有问题。但是,所有这些似乎都可以查看文档和我能找到的所有示例代码,以及我挖出的所有Stack Overflow线程。

我搞砸了什么?为什么其中一个参数不适合iOS?如果删除了可疑违规属性,我可以毫无问题地解码数据,因此我确信我的密码数据字典不是问题。我的伤害是什么?

1 个答案:

答案 0 :(得分:0)

我花了更多时间在example code from Apple上,并仔细查看了与SecItemAdd()一起使用的钥匙串查询字典。

我的问题是包含了不必要的属性键。的 kSecAttrAccessible

这弄乱了作品。

以下是传递给SecItemAdd()的字典中包含的适当键列表:

kSecClassGenericPassword
kSecAttrService
kSecAttrAccount (optional)
kSecValueData
kSecUseNoAuthenticationUI
kSecAttrAccessControl
kSecUseAuthenticationContext

我希望这可以节省一些人的头脑。