使用 iphone sdk 保存钥匙串时出错
我使用 Apple 钥匙串包装,并且尝试在其上保存一个项目(在模拟器中运行,ios 4.1)。
我以前没有使用过钥匙扣的经验。
我收到此错误:
无法添加钥匙串项目。错误 - 25299
在 KeychainItemWrapper.m 第 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." );
这就是我进行保存的方式:
- (void) saveKey:(NSString *)key value:(NSString *)value {
KeychainItemWrapper *keyItem = [[KeychainItemWrapper alloc] initWithIdentifier:key accessGroup:nil];
[keyItem setObject:value forKey:(id)kSecValueData];
[keyItem release];
}
这是 api 尝试保存的值:
<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"}
}
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"}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我知道这是几个月前的事,但我也遇到了同样的问题,而且很痛苦,所以我想分享一下。我通过添加这一行解决了这个问题:
我发现这个博客条目非常有帮助:
“用数据库术语来说,您可以认为它们是 kSecAttrAccount 和 kSecAttrService 这两个属性的唯一索引,要求这两个属性的组合对于钥匙串中的每个条目都是唯一的。” (来自 http://useyourloaf.com /blog/2010/4/28/keychain-duplicate-item-when-adding-password.html)。
此外,在 Apple 使用此代码的示例项目中,他们在应用程序委托中实例化 KeychainItemWrapper。我不知道是否有必要,但我喜欢尽可能密切地遵循他们的示例:
我认为这是包装器代码中的一个错误。逻辑基本上是说“这个条目已经存在吗?不,不存在。好吧,我会添加它。哎呀,你不能添加它,因为它已经存在了。”
您可能还需要设置kSecAttrAccount;我从未尝试过在不设置此值的情况下使用它,因为它的目的是保存与密码一起使用的用户名:
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:
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:
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:
根据 文档,您收到的错误-25299是“errSecDuplicateItem”,这意味着您尝试添加的项目已经存在。查看 KeychainItemWrapper 的链接代码,我猜想
SecItemCopyMatching
调用失败,并出现除 errSecItemNotFound (–25300) 之外的错误。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).您可以使用 Buzz Andersen 的 SFHFKeychainUtils 通过钥匙串轻松存储和取回值。
这是一个有关如何使用此库的小示例。
You can easily store and get back values with keychain using SFHFKeychainUtils by Buzz Andersen.
This is a little example on how to use this library.
钥匙扣真是太痛苦了。您应该使用 Buzz Andersen 的 STUtils 库作为包装器。它将使您的生活变得更加轻松。我从来没有遇到过问题。
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.
我也遇到了这个问题,并通过接受者的答案和 useyourloaf 的附加链接解决了它。
我遇到的问题很有趣,我只需要保存一个值,并决定将其存储在 kSecValueData 字段中。这是因为我看到了其他关于使用钥匙串的帖子,并在转向 KeychainItemWrapper 之前开始了自己的实现。
这导致了以下问题:在我测试的第一台设备(iPad 第一代)上,我在 writeToKeychain 中遇到错误。我更换了设备(也是第一代 ipad),它成功了!回到第一个设备,它仍然无法工作。
所以我知道我之前在设备的钥匙串中做错了一些事情并且无法轻松恢复。我收到的错误代码是:writeToKeychain 的 SecItemCopyMatching(未找到项目)上的 -25300 以及 SecItemAdd 上的 -25299 之后。 (项目重复)
对于这个问题,这一切都有意义:设备有一个与任何新密钥匹配的密钥,但 KeychainItemWrapper 无法删除它,但无法检索该密钥。
一旦我向 kSecAttrAccount 字段添加相同的值,它就开始工作。
长话短说,对于遇到此问题的其他用户来说,您的问题可能看起来有所不同,但请注意细节。如果您有 -25300(未找到项目),然后是 -25299(项目重复);确保您设置的字段定义了钥匙串项目的唯一性。如果它在一台设备上不起作用,请尝试另一台设备(如果可以),您也许能够将问题隔离到一台设备上。
Apple 钥匙串错误代码: http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898-CH5g- CJBEABHG(搜索结果代码)
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 field kSecValueData. 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)
对我来说,解决方案是创建一个 KeychainItemWrapper“单例”并在整个应用程序中使用它。 (实际上,就我而言,我有一个充满
KeychainItemWrapper
-s 的单例字典,因为我使用了多个。)这解决了我进入一个代码路径的问题,该路径有效地表示“钥匙串上存在这个项目吗?然后添加它,我正在尝试添加一个已经存在的项目(错误-25299)”
虽然我不确定,我怀疑问题与钥匙串同步有关。我在
NSUserDefaults
上遇到了类似的问题,当我写入 NSUD 时,然后在代码中的其他地方,获取standardUserDefaults
并从中读取,并且更新尚未发生然而(因为我还没有完成[ud Synchronize]
。)在代码中,我的例程如下所示:
并且我像这样使用它:(
等等,在其他地方有类似的调用。)
For me, the solution was that I created a
KeychainItemWrapper
"singleton" and use that throughout the app. (Actually, in my case, I had a singleton dictionary full ofKeychainItemWrapper
-s, because I use more than one.)This solved the problem where I was getting to a code path that effectively said "does this item exist on the keychain? No? Then add it. Whoops!
NSAssert()
that I'm trying to add an item that already exists (Error -25299)"While I'm not certain, I suspect that the problem has to do with keychain syncing. I've had similar problems with
NSUserDefaults
, when I write to NSUD then, elsewhere in code, get thestandardUserDefaults
and read from them, and the update hasn't taken place yet (because I haven't done[ud synchronize]
, yet.)In code, my routine looks like this:
And I use it like this:
(etc., similar calls in other places.)
我尝试了上面听的所有解决方案,但没有任何效果对我有用。它仅适用于实际设备,但不适用于模拟器。
我在模拟器上运行它的解决方案是打开“共享钥匙串权利”。
共享钥匙串权利
I tried all solutions listen above but nothing worked for me. It was only working on an actual device but not on the simulator.
My solution to run it on the simulator was to turn on "Share keychain entitlement".
Share Keychain entitlement