【问题标题】:How do I successfully delete an item from keychain in OS X?如何在 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属性。结果,我开始使用SecKeychainFindGenericPassword 和SecKeychainItemDelete。这将成功删除密码,但是随后为同一帐户添加不同的密码可能会导致崩溃。因此,我开始使用SecKeychainItemModifyAttributesAndData修改密码,不要删除密码。我相信这种不稳定性可能是由于 API 执行的缓存。

【问题讨论】:

    标签: objective-c c macos keychain


    【解决方案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 属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    相关资源
    最近更新 更多