如何在 OS X 中成功从钥匙串中删除项目?

Posted

技术标签:

【中文标题】如何在 OS X 中成功从钥匙串中删除项目?【英文标题】:How do I successfully delete an item from keychain in OS X? 【发布时间】:2014-05-01 19:50:49 【问题描述】:

如何在 OS X 中成功地从钥匙串中删除项目?这是我到目前为止所拥有的,但在SecItemDelete 调用中失败了。我需要在查询字典中指定一些额外的属性吗?通过执行类似的操作,我可以成功地将键值对插入到钥匙串中。

#define DELETE_SIZE 3
bool delete_key_keychain( const char *cKeyValue, SecKeychainRef keychain) 
    if ( !keychain)
        return false;

    // Convert to CFString.
    CFStringRef keyValue = CFStringCreateWithCString( NULL, cKeyValue, kCFStringEncodingUTF8);
    if ( !keyValue)
        return false;

    // Specify query parameters.
    const void *keys[DELETE_SIZE] = 
        kSecClass,
        kSecUseKeychain,
        kSecAttrAccount
    ;
    const void *values[DELETE_SIZE] = 
        kSecClassGenericPassword,
        keychain,
        keyValue
    ;

    // Create query.
    CFDictionaryRef query = CFDictionaryCreate( NULL, keys, values, GET_SIZE, NULL, NULL);
    if ( !query) 
        CFRelease( keyValue);
        return false;
    

    // Run query.
    OSStatus status = SecItemDelete( query);
    CFRelease( query);
    CFRelease( keyValue);

    return status == errSecSuccess;

更新:根据这个link,我需要在查询中设置kSecAttrService属性。结果,我开始使用SecKeychainFindGenericPasswordSecKeychainItemDelete。这将成功删除密码,但是随后为同一帐户添加不同的密码可能会导致崩溃。因此,我开始使用SecKeychainItemModifyAttributesAndData修改密码,不要删除密码。我相信这种不稳定性可能是由于 API 执行的缓存。

【问题讨论】:

【参考方案1】:

过去,我使用此功能从我的 Mac OS 钥匙串中删除特定的公钥/私钥对项目

// remove keypair from keychain
- (BOOL)deleteKeysFromKeychain 
    OSStatus sanityCheck1 = noErr;
    OSStatus sanityCheck2 = noErr;

    NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init];
    NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init];

    // Set the public key query dictionary.
    [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
    [queryPublicKey setObject:self.myPublicTag forKey:(__bridge id)kSecAttrApplicationTag];
    [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

    // Set the private key query dictionary.
    [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
    [queryPrivateKey setObject:self.myPrivateTag forKey:(__bridge id)kSecAttrApplicationTag];
    [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

    // Delete the private key.
    sanityCheck1 = SecItemDelete((__bridge CFDictionaryRef)queryPrivateKey);

    // Delete the public key.
    sanityCheck2 = SecItemDelete((__bridge CFDictionaryRef)queryPublicKey);

    @autoreleasepool 
        queryPrivateKey = nil;
        queryPublicKey = nil;
    

    return ( sanityCheck1 == sanityCheck2  && sanityCheck2 == noErr ? YES : NO );    

myPublicTag 类似于 'com.yourAppName.publickey'

myPrivateTag 类似于 'com.yourAppName.privatekey'

也许这会有用

【讨论】:

感谢您的回复。原来问题是我没有在查询中设置kSecAttrService 属性。

以上是关于如何在 OS X 中成功从钥匙串中删除项目?的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式在 OS X 钥匙串中存储对称密钥

在 icloud 钥匙串中保存密码

詹金斯删除钥匙串中的钥匙

即使在从钥匙串访问和 App Store Connect 中删除后,重新启动 Xcode 时,已删除的 iOS 证书仍会继续显示在钥匙串中

sh 测试从钥匙串中提取令牌并删除所有对话

访问钥匙串中的安全项目有时会在 iOS 中返回错误 -25308 (errSecInteractionNotAllowed)