首页 文章

为什么SecPKCS12Import会自动将SecIdentities添加到Keychain?

提问于
浏览
3

SecPKCS12Import上的documentation表示以下内容:

[...]然后,您可以使用Keychain Services API(请参阅Keychain Services Reference)将身份和相关证书放入钥匙串中 .

这意味着“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_);

如果您使用该代码然后打开Keychain Access,您将看到证书和私钥已添加到钥匙串中 .

问候,大卫 .

2 回答

  • 1

    似乎Apple的文档可能已经过时了(SecPKCS12Import),因为这个链接https://developer.apple.com/library/ios/qa/qa1745/_index.html提到"reading in a PKCS#12-formatted blob and then importing the contents of the blob into the app's keychain using the function SecPKCS12Import..."

    按照文档修订日期,QA1745比证书,密钥和信任服务参考更新 .

  • -1

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

相关问题