使用电子邮件地址在钥匙串中搜索证书

时间:2014-03-18 22:09:48

标签: ios certificate keychain

我正在尝试使用电子邮件地址直接在钥匙串中搜索证书。这就是我现在所拥有的:

OSStatus status = errSecSuccess;


CFMutableDictionaryRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue);
CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll);
CFDictionaryAddValue(query, kSecClass, classType);
CFDictionaryAddValue(query, kSecMatchEmailAddressIfPresent, (__bridge const void *)(emailAddress));

CFArrayRef result = nil;
status = SecItemCopyMatching(query, (CFTypeRef *)&result);
NSLog(@"Retrieved Item from Keychain With PersistedRef - Status: %@", [self tradeStatusForString:status]);


if (query)
    CFRelease(query);

if(status != errSecSuccess)
    return nil;
else
    return result;

但是,我使用电子邮件地址获取所有证书而不是证书。我知道这些证书有电子邮件地址,所以我不确定这里有什么不对。

感谢任何帮助,谢谢!

2 个答案:

答案 0 :(得分:1)

我永远无法让kSecMatchEmailAddressIfPresent正常工作,但找到了另一种解决方案。

在钥匙串中存储物品时,可以设置属性。因此,当我存储证书时,我将kSecAttrLabel设置为电子邮件地址。

NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
[query setValue:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnPersistentRef];
[query setValue:(__bridge id)item forKey:(__bridge id)kSecValueRef];
[query setValue:(id)emailAddress forKey:(__bridge id)kSecAttrLabel];

NSData *returnData = nil;
status = SecItemAdd((__bridge CFDictionaryRef)query, (void *)&returnData);

然后在查找证书时,我会将kSecAttrLabel作为搜索参数。

NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
[query setValue:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit];
[query setValue:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnPersistentRef];
[query setValue:(__bridge id)classType forKey:(__bridge id)kSecClass];
[query setValue:(id)emailAddress forKey:(__bridge id)kSecAttrLabel];

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

这对我有用,因为我已经知道证书绑定的电子邮件地址。但是,如果您事先不知道该电子邮件,则可以从kSecPolicyName(Security Policy Keys)或openssl中提取它。

答案 1 :(得分:0)

我没有使用Keychain Services API的经验,但我注意到kSecMatchEmailAddressIfPresent API docs表示:

  

[...]返回的证书或身份仅限于包含地址或不包含任何电子邮件地址的证书或身份。

[强调我的]

因此,对您而言,您的搜索结果包含的证书数量多于包含您要查找的电子邮件地址的证书,这并不奇怪。

不幸的是,似乎API无法从搜索结果中排除没有电子邮件地址的证书(至少我没有找到任何看起来有用的东西),所以你可能需要检查项目在手动搜索结果数组中。

如果您指定kSecMatchItemList,则可以将搜索结果数组反馈回SecItemCopyMatching。这可能有助于迭代缩小搜索范围,但前提是您可以提出其他聪明的搜索条件。