我正在编写一个将密码存储在钥匙串上的应用程序,然后使用SecKeychainFindGenericPassword()获取它们。这种工作文件有90%的时间,但每隔一段时间,对SecKeychainFindGenericPassword()的调用将失败并出现errSecAuthFailed(-25293)。当它发生时,只需再次尝试,或重新启动应用程序即可修复它。
有没有人知道造成这种情况的原因是什么?一般谷歌搜索此错误指向钥匙串损坏或钥匙串被锁定 - 这两种情况都不是这样,因为后续调用再次成功...
答案 0 :(得分:1)
此链接表明您输入的密码不正确。 See Here 有时你有可能只是偶然发送一个空对象作为密码短语吗?
或者,您可以尝试EMKeychain。我在GitHub上有一个更新的版本:http://github.com/ctshryock/EMKeychain
答案 1 :(得分:1)
您还没有围绕您的问题分享代码,所以我只是猜测您的问题不是功能失调的钥匙串,而是一些编码错误。
这是一个常见的陷阱:由于KeyChain API是' C',并且它们只接受C样式的空终止字符串缓冲区,因此您通常需要将CFString / NSString对象转换为C缓冲区在将它们交给API之前。
许多人使用以下内容:
const char *usernameCStr = [username UTF8String];
对于NSString或其CFString伴侣......
const char *CFStringGetCStringPtr(CFStringRef theString, CFStringEncoding encoding); /* May return NULL at any time; be prepared for NULL */
忽略这些API可能返回NULL的事实。要么是因为CF / NSString的内部缓冲区是非连续的,要么不是您要求的编码,或者不兼容。
这样的问题可以在运行时完全像你描述的那样。
在这种情况下,您应该发现问题并使用不同的API将CF / NS字符串复制到C缓冲区中:
Boolean CFStringGetCString(CFStringRef theString, char *buffer, CFIndex bufferSize, CFStringEncoding encoding);
或
- (BOOL)getCString:(char *)buffer maxLength:(NSUInteger)maxBufferCount encoding:(NSStringEncoding)encoding;
答案 2 :(得分:0)
我不确定这是不是问题(我不知道它是怎么回事)但我最近改变了我的代码以正确传递cStrings的strlen()
,而不是NSString
{ {1}}进入通话。从技术上讲,这更正确(因为如果涉及UTF-8双字节字符,字符串长度可能与cString不同。
但是,我测试过的用户名/密码都没有包含非ASCII字符,所以我不知道这个问题究竟是如何影响我看到的错误的。我的新代码如下,我没有看到它的错误:
UInt32 length;
void *data;
const char *account = [[BC_HOST stringByAppendingFormat:@":%@", login] cStringUsingEncoding:NSUTF8StringEncoding];
NSLog(@"Getting password from keychain.");
OSStatus s = SecKeychainFindGenericPassword (nil,
strlen(BC_APPNAME), BC_APPNAME,
strlen(account), account,
&length, &data, &keychainItem);
if (s != 0) NSLog(@"Error %d obtaining password from keychain.", s);
if (s == 0)
{
password = [[NSString alloc] initWithBytes:data length:length encoding:NSUTF8StringEncoding];
}
答案 3 :(得分:0)
我遇到了同样的问题,在我看来,事实证明这是原因:Cannot access keychain item after SMJobBless update
答案 4 :(得分:0)
发生此问题的一个可能原因是,进行调用的可执行文件无法访问钥匙串项。在Keychain Access中,您可以看到有权访问相关项目的“访问控制”选项卡下的项目的应用程序列表。
如果您的应用从其他位置运行,则会出现此错误。例如,我有一个Privileged Helper Tool,在我的开发机上,我通常以root身份运行Xcode。此可执行文件的路径是Xcode创建它的路径,它是〜/ Library / Developer / Xcode / DerivedData // myexecutable中的路径。当我以用户身份运行它时,它从/ Library / PrivilegedHelperTools / myexecutable运行。因此,如果密码最初是由应用程序的一个版本创建的,并且我尝试使用其他路径读取密码,我将看到errSecAuthFailed错误。
这不是唯一的原因。其他人提到了SMJobBless所具有的升级问题。这也可能导致相同的错误代码,但我确实看到它有两个原因 - 尽管我通过命令帮助工具在升级之前将其自身移动到不同的位置,以编程方式解决了就地升级问题。