OSX 10.9 Mavericks にアップグレードして以来、Keychain 関数が呼び出されるたびに不明な例外がスローされるため、Security フレームワークで Keychain API を使用できませんでした。キーチェーン ラッパーのさまざまな実装を試してみましたが、いずれもキーチェーン関数を呼び出すと不明な例外がスローされます。Apple の開発者サイトに投稿されたサンプル コードを試してみたところ、同じ問題が発生しました。これは既知の問題ですか? もしそうなら、修正の状況はどうなっていますか? キーチェーンを使用する方法はありますか? Apple の Web サイトからサンプル コードを以下に示します。リンクは次のとおりです。
#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);
}