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

时间:2014-05-01 19:50:50

标签: objective-c c macos keychain

如何在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 个答案:

答案 0 :(得分:0)

过去,我使用此功能从我的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'

也许这可能有用