Macos SecItemCopyMatching-按名称查找特定的kSecClassIdentity

Macos SecItemCopyMatching-按名称查找特定的kSecClassIdentity,macos,keychain,Macos,Keychain,我试图在我的Mac OS X钥匙链中根据其名称(kSecAttrLabel)查找特定条目,但它看起来像SecItemCopyMatching被破坏了,在查找类型为:kSecClassIdentity的条目时不应用任何筛选 这段代码将返回all钥匙链中找到的all标识,尽管kSecAttrLabel:@“MyIdentity”参数: NSDictionary *query = @{ (__bridge id)kSecClass: (__bridge NSString*)kSecClassIdent

我试图在我的
Mac OS X钥匙链中根据其名称(
kSecAttrLabel
)查找特定条目,但它看起来像
SecItemCopyMatching
被破坏了,在查找类型为:
kSecClassIdentity
的条目时不应用任何筛选

这段代码将返回all钥匙链中找到的all标识,尽管
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()
从我的密钥链中删除这个标识,它将查询作为参数,就像
secitemcopymatting
。 如果过滤不适用于
SecItemCopyMatching
,那么它很可能不适用于
SecItemDelete
,这意味着如果我尝试使用此查询调用
SecItemDelete
,我只会删除我的密钥链的内容


我做错了什么?

我遇到了类似的问题,但我使用的是kSecAttrApplicationTag而不是kSecAttrLabel。我不是objective 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);

我想我刚刚找到了一个解决办法。有人就此提出建议

在标识上使用标签很棘手,因为标识不是作为原子项存储在密钥链中,而是作为单独的私钥和证书存储,并且这些项以不同的方式使用标签

这使我意识到一个解决方案是使用
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
    }
}