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
}
}