在Keychain Services中使用SecItemUpdate

时间:2013-11-21 17:51:15

标签: ios iphone cocoa-touch keychain

我有以下代码在钥匙串中创建钥匙串项目:

    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 =

  

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

2 个答案:

答案 0 :(得分:6)

SecItemUpdate非常有记录。

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

attributes参数应该是SecItemCopyMatching的结果,其中kSecValueData键和值已添加且任何属性都已更改。

答案 1 :(得分:4)

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

我一直在努力更新钥匙串中的物品,但我的情境有点不同。

发生了什么:

我可以成功添加一个钥匙串项目(使用SecItemAdd),但在同一个项目上调用SecItemUpdate失败了,而臭名昭着的errSecParam -50。 更糟糕的是;如果钥匙串项已经存在(因此我立即调用SecItemUpdate),更新完全没有问题。
我完全不知道为什么会发生这种情况......

我如何解决它:

实际上非常简单,我只是删除了“params”,直到大坏-50满意为止。当我从kSecClass检索到的词典中删除kSecItemCopyMatching时发生了这种情况 这是我的代码:

 // 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为我解决了问题。