在钥匙链服务中使用SecItemUpdate



我有以下代码在钥匙链中创建一个钥匙链项目:

    NSMutableDictionary* dict = [NSMutableDictionary dictionary];
    [dict setObject: (__bridge id) kSecClassGenericPassword  forKey: (__bridge id) kSecClass];
    [dict setObject: MYKEY           forKey: (__bridge id) kSecAttrService];
    [dict setObject: @"0" forKey: (__bridge id) kSecValueData];
    SecItemAdd ((__bridge CFDictionaryRef) dict, NULL);

这很好用。如果我想更改此项,有人能给出SecItemUpdate的语法吗?

更新:包含以下内容:

NSMutableDictionary *query = [NSMutableDictionary dictionary];
NSMutableDictionary *attributesToUpdate = [NSMutableDictionary dictionary];
[query setObject: (__bridge id) kSecClassGenericPassword forKey: (__bridge id) kSecClass];
[query setObject: MYKEY forKey: (__bridge id) kSecAttrService];
[query setObject: (id) kCFBooleanTrue forKey: (__bridge id) kSecReturnData];
NSString *numberOfBalloonsString = [NSString stringWithFormat:@"%d", numberOfBalloonsUsed];
NSData *numberOfBalloonsData = [numberOfBalloonsString dataUsingEncoding:NSUTF8StringEncoding];
[attributesToUpdate setObject: numberOfBalloonsData forKey:(__bridge id)kSecValueData];
OSStatus error = SecItemUpdate ((__bridge CFDictionaryRef) query, (__bridge CFDictionaryRef) attributesToUpdate);
NSLog(@"Error #: %ld", error);

我得到错误代码-50=

传递给函数的一个或多个参数无效。

SecItemUpdate的文档非常丰富。

SecItemUpdatequery参数记录为一个查询(在其他函数中使用)以及一个模糊的语句:"指定要更改其值的项"。这似乎意味着你必须在这个字典中包含你想要更改的现有属性值,但我不认为你这样做。我发现你可以使用相同的query来获取你想要更新的项目的属性。

attributes参数应该是添加了kSecValueData键和值并更改了任何属性的SecItemCopyMatching的结果。

一个迟来的答案,但仍然是一个答案:

我也一直在努力更新钥匙链中的项目,不过我的上下文有点不同。


发生了什么:

我可以成功地添加一个密钥链项目(使用SecItemAdd),但在同一个项目上调用SecItemUpdate失败,出现了臭名昭著的errSecParam -50
更糟糕的是;如果钥匙链项目已经存在(因此我立即调用了SecItemUpdate),那么更新就顺利完成了
我完全不知道为什么会发生这种事。。。

我是如何修复的:

实际上很简单,我只是删除了"params",直到大坏的-50得到满足。当我从kSecItemCopyMatching检索到的字典中删除kSecClass时,就发生了这种情况
这是我的代码:

 // If the item already exists, we update it instead
if (SecItemCopyMatching((__bridge CFDictionaryRef)self.searchQueryDict, (CFTypeRef *)&foundItem) == errSecSuccess) {
    NSMutableDictionary *updateDict = (__bridge NSMutableDictionary *)foundItem;
    [updateDict addEntriesFromDictionary:dictToSave];
    [updateDict removeObjectForKey:(__bridge id)kSecClass];
    OSStatus updateSuccess = SecItemUpdate((__bridge CFDictionaryRef)self.updateQueryDict,
                                           (__bridge CFDictionaryRef)updateDict);
    NSAssert(updateSuccess == errSecSuccess, @"Couldn't save the dirty info to the keychain, might want to log the updateSuccess (%d)", updateSuccess);
}

作为参考,我使用了以下词典

包含self.searchQueryDict

(__bridge id)kSecClass              : (__bridge id)kSecClassGenericPassword              
(__bridge id)kSecAttrService        : service                                            
(__bridge id)kSecAttrGeneric        : [identifier dataUsingEncoding:NSUTF8StringEncoding]
(__bridge id)kSecMatchLimit         : (__bridge id)kSecMatchLimitOne                     
(__bridge id)kSecReturnAttributes   : (__bridge id)kCFBooleanTrue                        
(__bridge id)kSecReturnData         : (__bridge id)kCFBooleanTrue                        

包含self.updateQueryDict

(__bridge id)kSecClass       : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService : service,
(__bridge id)kSecAttrGeneric : [identifier dataUsingEncoding:NSUTF8StringEncoding]

dictToSave应包含需要更改的值(格式正确)

删除kSecClass为我解决了问题。

最新更新