我试图在我的Mac OS X keychain
中根据它的名称(kSecAttrLabel
)查找特定条目,但看起来SecItemCopyMatching
已被破坏,在查找类型为kSecClassIdentity
的项目时,不会应用任何过滤。
这段代码将返回所有钥匙串中的所有标识,尽管kSecAttrLabel: @"MyIdentity"
参数:
NSDictionary *query = @{ (__bridge id)kSecClass: (__bridge NSString*)kSecClassIdentity,
(__bridge id)kSecAttrLabel: @"MyIdentity",
(__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitAll,
(__bridge id)kSecReturnAttributes: @YES,
(__bridge id)kSecReturnRef: @YES };
OSStatus status;
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&privateKey);
当然,我可以通过手动过滤返回的数组来找到我正在寻找的一个身份,但是,除了IMHO
之外,它应该正常工作,我还想删除来自我的钥匙串的此身份使用SecItemDelete()
,它将查询作为参数,就像SecItemCopyMatching
一样。
如果过滤不适用于SecItemCopyMatching
,那么它很可能无法为SecItemDelete
工作,这意味着如果我尝试拨打,我将简单地删除我的钥匙串的内容SecItemDelete
使用此查询。
我做错了什么?
答案 0 :(得分:0)
我有类似的问题,但我使用的是kSecAttrApplicationTag而不是kSecAttrLabel。无论如何,我不是客观的c也不是IOS安全专家。事实证明我用来创建查找标记的方法不正确。这对我有用:
- (void) getOrCreateKey: (NSNumber*)bits publicIdentifier:(NSString*)publicID
// no! This appears in several samples, but did not work for me on iOS
// NSData * publicLookupTag = [NSData dataWithBytes:publicId length:strlen((const char *)publicId)];
//
// yes!
NSData * publicLookupTag = [NSData dataWithBytes:[publicId UTF8String] length:publicId.length];
NSMutableDictionary *queryPublicKey = [[NSMutableDictionary alloc] init];
[queryPublicKey setObject:(id)kSecClassKey forKey:(id)kSecClass];
[queryPublicKey setObject:publicLookupTag forKey:(id)kSecAttrApplicationTag];
[queryPublicKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];
OSStatus lookupStatus = noErr;
lookupStatus = SecItemCopyMatching((CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicLookupKey);
答案 1 :(得分:0)
我想我刚刚找到了解决方案。在on another forum上有人建议
在身份上使用标签很棘手,因为身份不是作为原子项存储在钥匙串中,而是作为单独的私钥和证书存储,并且这些项以不同的方式使用标签。
这使我意识到一种解决方案是使用SecItemCopyMatching
按标签搜索证书,然后使用SecIdentityCreateWithCertificate
创建身份。后者的调用应在钥匙串中找到匹配的私钥。这是似乎在macOS Mojave上对我有用的完整代码(在C ++中):
SecIdentityRef identity = nullptr;
const char* certificateName = ...;
const void* keys[] = {
kSecClass,
kSecMatchLimit,
kSecReturnRef,
kSecAttrLabel
};
const void* values[] = {
kSecClassCertificate,
kSecMatchLimitOne,
kCFBooleanTrue,
CFStringCreateWithCString(nullptr, certificateName, kCFStringEncodingUTF8)
};
CFDictionaryRef query = CFDictionaryCreate(nullptr, keys, values, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFTypeRef result;
OSStatus status = SecItemCopyMatching(query, &result);
CFRelease(query);
CFRelease(values[3]);
if (status) {
// error
}
else {
SecCertificateRef certificate = (SecCertificateRef)result;
status = SecIdentityCreateWithCertificate(nullptr, certificate, &identity);
CFRelease(certificate);
if (status) {
// error
}
}