为什么SecPKCS12Import会自动将SecIdentities添加到钥匙串?
上SecPKCS12Import的documentation规定如下:为什么SecPKCS12Import会自动将SecIdentities添加到钥匙串?
[...]然后,您可以使用Keychain服务API(参见Keychain服务 参考)把身份和相关的证书,在 钥匙串。
这意味着在“items”参数(该函数的第三个参数)中返回的项目不应该自动添加到钥匙串中。但是,我发现这些项目在使用该功能时会自动添加到钥匙串中。如果我尝试使用SecItemAdd添加它们,我会得到errSecDuplicateItem。
这是一个错误还是应该这样?为什么会自动添加项目?
下面是一些示例代码:
NSDictionary *options = [[NSDictionary alloc] initWithObjectsAndKeys:@"password", (id)kSecImportExportPassphrase, nil];
CFArrayRef items_ = NULL;
OSStatus ret = SecPKCS12Import((CFDataRef)pkcs12data /* get this from somewhere … */, (CFDictionaryRef)options, &items_);
如果您使用的代码,然后打开钥匙串访问,您将看到证书和私钥已被添加到钥匙串。
Regards, David。
好像苹果的文档可能会过时该链接(SecPKCS12Import),因为这个环节https://developer.apple.com/library/ios/qa/qa1745/_index.html提到,“在读一PKCS#12格式的斑点,然后导入Blob的内容到应用程序的钥匙扣使用功能SecPKCS12Import ...“
按照文档修订日期,QA1745比证书,密钥和信任服务参考更新。
SecPKCS12Import
不会将项目添加到钥匙串中。但是,它会在钥匙串中查看导入的项目是否已经存在。如果它找到现有项目,将返回SecIdentityRef (SecCertificateRef and SecKeyRef)
。这就是为什么在致电SecPKCS12Import
后致电SecItemAdd
时您可以获得errSecDuplicateItem
。
调试时,您可能希望使用这样的代码在你的钥匙链,除去一切:
void _EraseKeychain()
{
NSMutableArray *toDelete = [NSMutableArray array];
NSArray *classes = @[(__bridge id)kSecClassCertificate,
(__bridge id)kSecClassKey,
(__bridge id)kSecClassIdentity,
(__bridge id)kSecClassInternetPassword,
(__bridge id)kSecClassGenericPassword];
NSMutableDictionary *query = [NSMutableDictionary dictionary];
query[(id)kSecClass] = (__bridge id)kSecClassIdentity;
query[(id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll;
query[(id)kSecReturnPersistentRef] = @YES;
id class;
for(class in classes)
{
query[(__bridge id)kSecClass] = class;
CFTypeRef items = nil;
OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)query, &items);
if(result == errSecSuccess)
{
[toDelete addObjectsFromArray:(__bridge NSArray*)items];
CFRelease(items);
}
}
id deleteRef;
for(deleteRef in toDelete)
{
NSString *objectKind = @"unknown";
if(CFGetTypeID(deleteRef) == CFDataGetTypeID())
{
objectKind = [[NSString alloc] initWithUTF8String:(char *)[(__bridge NSData*)deleteRef bytes]];
}
NSDictionary *delRequest = @{(id)kSecValuePersistentRef:deleteRef};
OSStatus deleteResult = SecItemDelete((__bridge CFDictionaryRef)delRequest);
if(deleteResult == errSecSuccess)
NSLog(@"Deleted item(%@) with persistent ref %@", objectKind, deleteRef);
else if(deleteResult == errSecItemNotFound)
NSLog(@"Already deleted item(%@) with persistent ref %@", objectKind, deleteRef);
else
NSLog(@"Can't delete keychain item(%@) with persistent ref %@", objectKind, deleteRef);
}
}
'SecIdentityRef'是证书/密钥对的别名。如果删除它,您将删除与之匹配的证书和密钥。如果你删除了证书和密钥,那么'SecIdentityRef'将失效。 –
您可以在https://opensource.apple.com/source/libsecurity_keychain/libsecurity_keychain-55050.9/lib/SecImportExport.c中清楚地看到SecPKCS12Import确实会将其导入钥匙串中,并且事实上在使用此功能时无法阻止它功能。 –
您可能要问了一个新问题,而不是在现有的一个张贴一个答案。 – JAL
编辑删除末尾的问题 – satishmaha