Error saving in the keychain with iphone sdk

I use the Apple wraper for the keychain, and try to save a item on it (running in simulator, ios 4.1).

I have not experience with the keychain before.

I get this error:

Couldn't add the Keychain Item. Error - 25299

In KeychainItemWrapper.m line 304:

// No previous item found; add the new one.
result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL);
NSAssert( result == noErr, @"Couldn't add the Keychain Item." );

This is how I do the save:

- (void) saveKey:(NSString *)key value:(NSString *)value {
    KeychainItemWrapper *keyItem = [[KeychainItemWrapper alloc] initWithIdentifier:key accessGroup:nil];
    [keyItem setObject:value forKey:(id)kSecValueData];
    [keyItem release];
}

And this are the values that the api try to save:

<CFBasicHash 0x7231f60 [0x320d380]>{type = mutable dict, count = 5,
entries =>
2 : <CFString 0x2e6eb98 [0x320d380]>{contents = "labl"} = <CFString 0x2fb018 [0x320d380]>{contents = ""}
3 : <CFString 0x2e6efb8 [0x320d380]>{contents = "v_Data"} = <CFString 0x727de60 [0x320d380]>{contents = "dit8"}
4 : <CFString 0x2e6ebc8 [0x320d380]>{contents = "acct"} = <CFString 0x2fb018 [0x320d380]>{contents = ""}
5 : <CFString 0x2e6eb58 [0x320d380]>{contents = "desc"} = <CFString 0x2fb018 [0x320d380]>{contents = ""}
6 : <CFString 0x2e6ebe8 [0x320d380]>{contents = "gena"} = <CFString 0x2ffd08 [0x320d380]>{contents = "userCode"}
}
share | improve this question
 
have you solved the problem?  –  Matthias Bauch   Apr 7 '11 at 20:28
 
I'm stuck with this, so I think a bounty is a good idea. Same errorCode but iOS4.3 But I guess this is a PEBKAC problem, and no problem with the sdk.  –  Matthias Bauch   Apr 7 '11 at 20:37
 
This problem occurred to me when I added [keychainItemData setObject:@"" forKey:(__bridge id)kSecAttrService]; in - (void)resetKeychainItem. Then when I was reading user379075's answer below, it rang a bell that if you 'reset' it, you also have to set it and v.v.  –  mrd3650   Apr 13 '12 at 15:52

5 Answers

up vote 15 down vote accepted

I know this is from several months ago, but I just had the same problem and it was painful so I thought I'd share. I solved it by adding this line:

[self.keychainItemWrapper setObject:@"MY_APP_CREDENTIALS" forKey:(id)kSecAttrService];
//@"MY_APP_CREDENTIALS" can be any string.

I found this blog entry very helpful: "In database terms you could think of their being a unique index on the two attributes kSecAttrAccount, kSecAttrService requiring the combination of those two attributes to be unique for each entry in the keychain." (from http://useyourloaf.com/blog/2010/4/28/keychain-duplicate-item-when-adding-password.html).

Also, in Apple's example project using this code, they instantiate KeychainItemWrapper in the app delegate. I don't know if it's necessary, but I like to follow their examples as closely as possible:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//there will be some standard code here.
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MY_APP_CREDENTIALS" accessGroup:nil];
self.keychainWrapper = wrapper;
[self.keychainWrapper setObject:@"MYOBJECT" forKey:(id)kSecAttrService];
[wrapper release];
}

I think this is a bug in the wrapper code. The logic basically says "Does this entry exist already? No, it doesn't. OK, I'll add it. Oops, you can't add it because it's already there."

You may also need to set kSecAttrAccount; I've never tried it without also setting this value since it's intended to save the username that goes with the password:

[self.wrapper setObject:txtUserName.text forKey:(id)kSecAttrAccount];   
share | improve this answer
 
Worked fine after adding the MY_APP_CREDENTIALS statement. Thanks a lot :)  –  ilight   Sep 3 '12 at 6:32
 
Awesome! Thanks! :-)  –  orange80   Dec 30 '12 at 1:27

According to the documentation, the error -25299 you are getting is "errSecDuplicateItem", meaning that the item you are trying to add already exists. Looking at the linked code for KeychainItemWrapper, I would guess that the SecItemCopyMatching call is failing with an error other than errSecItemNotFound (–25300).

share | improve this answer
   

You can easily store and get back values with keychain using SFHFKeychainUtils by Buzz Andersen.

  1. Download and copy in your project SFHFKeychainUtils.h and .m
  2. Add Security.framework to your Framework folder
  3. Make sure these files are added to your target
  4. Import SFHFKeychainUtils.h where you want to use it

This is a little example on how to use this library.

// To store data
NSError *error = nil;
[SFHFKeychainUtils storeUsername:username andPassword:password forServiceName:kStoredData updateExisting:YES error:&error];

// To retrieve data
NSString *password = [SFHFKeychainUtils getPasswordForUsername:username andServiceName:kStoredData error:&error];

// To delete data from keychain
[SFHFKeychainUtils deleteItemForUsername:username andServiceName:kStoredData error:&error];
share | improve this answer
 
What is kStoredData in this context? I'm getting a build error when trying to do this.  –  Philip Walton   Apr 21 '11 at 23:34
 
In this case kStoredData is a defined key... You can use any key... In this example, kStoreData is a key for a service name like @"com.company.app.serviceName". You can define a key like this in you .h file and then use it to store and retrieve your data  –  matteodv   Apr 22 '11 at 9:51

The keychain is a total pain. You should use Buzz Andersen's STUtils library instead as a wrapper. It will make your life substantially easier. I've never had a problem with it.

share | improve this answer
 
2  
This github project has now been deprecated; the author suggestsgithub.com/ldandersen/STUtils/blob/master/Security as a replacement.  –  Graham Miln   Oct 11 '12 at 10:25

I had this problem also and solved it thanks to the accepter answer and the additional link to useyourloaf.

The problem I had was interesting, I needed to save only one value and decided to store it in the fieldkSecValueData. That is because I saw other posts about using the keychain and started my own implementation before turning to KeychainItemWrapper. This caused the following issue: On the first device I was testing (iPad 1st gen) I was getting an error in writeToKeychain. I changed device (also ipad 1st gen) and it worked! Back to the first device it still didn't work.

So I that point I knew that I had previously done something wrong in the device's keychain and couldn't revert it easily. The error codes I was getting were: -25300 on the writeToKeychain's SecItemCopyMatching (item not found) and right after -25299 on the SecItemAdd. (item duplicate)

With this question, this all made sense: the device has a key that matches any new key but the KeychainItemWrapper cannot delete it but the key cannot be retrieved. As soon as I added the same value to the field kSecAttrAccount, it started working.

Long story short, for other users having this problem, your problem might look different but pay attention to the details. If you have -25300 (item not found) followed by -25299 (item duplicate); make sure that you are setting a field that defines the uniqueness of your keychain item. If it doesn't work on one device, try another if you can you might be able to isolate the problem to one device. Apple keychain Error codes:http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898-CH5g-CJBEABHG (search for Result Codes)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值