KeychainItemWrapper奇怪的行为,现有/不存在的项目错误与相同的项目

时间:2014-07-19 00:40:35

标签: ios keychain ios6.1

在Apple提供的KeychainItemWrapper类问题上遇到很多问题后,我可以让它工作,但后来我在代码上做了一些事情,看起来现在处于不稳定的状态。 实际上我有原始的KeychainItemWrapper类,我只是更改了以下行来检查结果:

OSStatus cpy = SecItemCopyMatching((CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes);
NSLog(@"cpy result=%d", cpy);
if (cpy == noErr)
{
  ....
}
else
{
  // No previous item found; add the new one.
  result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL);
  if(result == errSecDuplicateItem) {
      result = SecItemDelete((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData]);
      NSLog(@"result=%d", result);
  }
  NSAssert( result == noErr, @"Couldn't add the Keychain Item." );
}

第一个cpy变量返回-25300(无法找到该项)

SecItemAdd返回errSecDuplicateItem(-25299该项已存在)

然后我试图删除项目,如果函数说项目存在,SecItemDelete再次返回-25300,那么......现在我无法理解发生了什么。

我使用带有iOS 6.1.3的iPad运行此测试,不管怎样?有没有办法完全重置钥匙串并从头开始?

感谢您的帮助

1 个答案:

答案 0 :(得分:3)

我在此链接中提供的信息后发现了问题: What makes a keychain item unique (in iOS)?

"对于类kSecClassGenericPassword的keychain项,主键是kSecAttrAccount和kSecAttrService的组合。"

看起来Apple提供的KeychainItemWrapper示例类使用了错误的组合键,或者对我试图做的事情没有用。

无论如何我删除了那个类,现在我使用了一些简化的方法,我把代码放在这里,可能对其他人有帮助:

- (NSString*) getKeyChainItem:(NSString*)key {
  NSString* keyChainValue = NULL;
  NSData *attributes = NULL;

  NSMutableDictionary* keyChainParams = [self createKeyChainDict:key];
  [keyChainParams setObject:key forKey:(id)kSecAttrService];
  [keyChainParams setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];

  if (SecItemCopyMatching((CFDictionaryRef)keyChainParams, (CFTypeRef *)&attributes) == noErr)
  {
    keyChainValue = [[[NSString alloc] initWithBytes:[attributes bytes] length:[attributes length]
                                            encoding:NSUTF8StringEncoding] autorelease];
  }
  return keyChainValue;
}

- (BOOL) setKeyChainItem:(NSString*)key withValue:(NSString*)value {
  NSMutableDictionary* keyChainParams = [self createKeyChainDict:key];
  [keyChainParams setObject:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData];

  return SecItemAdd((CFDictionaryRef)keyChainParams, NULL) == noErr;
}

- (NSMutableDictionary*)createKeyChainDict:(NSString*)key {
  NSMutableDictionary* keyChainParams = [[NSMutableDictionary alloc] init];
  [keyChainParams setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
  [keyChainParams setObject:@"" forKey:(id)kSecAttrLabel];
  [keyChainParams setObject:@"" forKey:(id)kSecAttrDescription];
  [keyChainParams setObject:key forKey:(id)kSecAttrService];
  [keyChainParams setObject:key forKey:(id)kSecAttrAccount];
  return keyChainParams;
}

如何使用它:

NSString* myValue = [self getKeyChainItem:@"myStoredVvalue"];

[self setKeyChainItem:@"myStoredVvalue" withValue:@"12345"];