OSX 10.9 Mavericks 钥匙串 API 坏了?

Posted

技术标签:

【中文标题】OSX 10.9 Mavericks 钥匙串 API 坏了?【英文标题】:OSX 10.9 Mavericks Keychain API Broken? 【发布时间】:2013-11-10 05:58:13 【问题描述】:

自从升级到 OSX 10.9 Mavericks 后,我一直无法在 Security 框架中使用 Keychain API,因为每次调用 Keychain 函数时,它都会引发未知异常。我尝试了许多不同的 Keychain 包装器实现,它们在调用任何 Keychain 函数时都会抛出未知异常。我什至尝试过苹果在他们的开发者网站上发布的示例代码并遇到了同样的问题。这是一个已知问题吗?如果是,修复的状态如何?他们现在有任何使用钥匙串的方法吗?我在下面包含了来自苹果网站的示例代码。这是链接:https://developer.apple.com/library/mac/documentation/Security/Conceptual/keychainServConcepts/03tasks/tasks.html#//apple_ref/doc/uid/TP30000897-CH205-TP9

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#include <CoreServices/CoreServices.h>

//Call SecKeychainAddGenericPassword to add a new password to the keychain:
OSStatus StorePasswordKeychain (void* password,UInt32 passwordLength)

 OSStatus status;
 status = SecKeychainAddGenericPassword (
                NULL,            // default keychain
                10,              // length of service name
                "SurfWriter",    // service name
                10,              // length of account name
                "MyUserAcct",    // account name
                passwordLength,  // length of password
                password,        // pointer to password data
                NULL             // the item reference
    );
    return (status);
 

//Call SecKeychainFindGenericPassword to get a password from the keychain:
OSStatus GetPasswordKeychain (void *passwordData,UInt32 *passwordLength,
                                                SecKeychainItemRef *itemRef)

 OSStatus status1 ;


 status1 = SecKeychainFindGenericPassword (
                 NULL,           // default keychain
                 10,             // length of service name
                 "SurfWriter",   // service name
                 10,             // length of account name
                 "MyUserAcct",   // account name
                 passwordLength,  // length of password
                 passwordData,   // pointer to password data
                 itemRef         // the item reference
    );
     return (status1);
 

//Call SecKeychainItemModifyAttributesAndData to change the password for
// an item already in the keychain:
OSStatus ChangePasswordKeychain (SecKeychainItemRef itemRef)

    OSStatus status;
    void * password = "myNewP4sSw0rD";
    UInt32 passwordLength = strlen(password);

 status = SecKeychainItemModifyAttributesAndData (
                 itemRef,         // the item reference
                 NULL,            // no change to attributes
                 passwordLength,  // length of password
                 password         // pointer to password data
    );
     return (status);
 


/* ********************************************************************** */

int main (int argc, const char * argv[]) 
    OSStatus status;
    OSStatus status1;

     void * myPassword = "myP4sSw0rD";
     UInt32 myPasswordLength = strlen(myPassword);

     void *passwordData = nil; // will be allocated and filled in by
                               //SecKeychainFindGenericPassword
     SecKeychainItemRef itemRef = nil;
     UInt32 passwordLength = nil;

    status1 = GetPasswordKeychain (&passwordData,&passwordLength,&itemRef);  //Call
                                                //SecKeychainFindGenericPassword
        if (status1 == noErr)       //If call was successful, authenticate user
                                    //and continue.
        
        //Free the data allocated by SecKeychainFindGenericPassword:
    status = SecKeychainItemFreeContent (
                 NULL,           //No attribute data to release
                 passwordData    //Release data buffer allocated by
                 //SecKeychainFindGenericPassword
    );
 

    if (status1 == errSecItemNotFound)  //Is password on keychain?
    /*
    If password is not on keychain, display dialog to prompt user for
    name and password.
    Authenticate user.  If unsuccessful, prompt user again for name and password.
    If successful, ask user whether to store new password on keychain; if no, return.
    If yes, store password:
    */
    status = StorePasswordKeychain (myPassword,myPasswordLength); //Call
                                                      // SecKeychainAddGenericPassword
    return (status);
    

    /*
    If password is on keychain, authenticate user.
    If authentication succeeds, return.
    If authentication fails, prompt user for new user name and password and
     authenticate again.
    If unsuccessful, prompt again.
    If successful, ask whether to update keychain with new information.  If no, return.
    If yes, store new information:
    */
    status = ChangePasswordKeychain (itemRef);  //Call
                                            // SecKeychainItemModifyAttributesAndData
    if (itemRef) CFRelease(itemRef);
    return (status);

 

【问题讨论】:

【参考方案1】:

您的应用程序是否正确签名?如果不是,许多调用将神秘地失败。我认为这开始发生在 10.8 左右。你得到什么错误代码?

【讨论】:

以上是关于OSX 10.9 Mavericks 钥匙串 API 坏了?的主要内容,如果未能解决你的问题,请参考以下文章

OSX 10.9 - Mavericks webdav 客户端锁定问题

OS X 10.9 Mavericks - 使用虚拟主机设置本地主机

在 migratePersistentStore: 到 OS X 10.9 Mavericks 上的另一个 URL 后访问 NSManagedObject 属性时崩溃

Aspell 不会在 OS X 10.9 (Mavericks) 上构建

在 OS X 10.9 (Mavericks) 上安装 Java

如何在 OS X 10.9 (Mavericks) 上使用 GDB 而不是 LLDB 调试 ELF 文件?