まずはサンプルコードを読んでみる。
Cocoa Example Code: Drink Holder | Simple Keychain Example
http://homepage.mac.com/agerson/examples/keychain/
username と password を keychain に登録・取得・削除などすることができるようだ。試しに登録(Add)してみた。
キーチェーンアクセス.app で見てみると:
登録できている。右クリックして詳しい情報を見てみる。
なるほど。いろいろな属性・オプションが設定できるようだ。
ソースコードを見てみよう。
AGKeychainController は名前の通りコントローラーの役割で、Keychain Services に関わる処理は AGKeychain が担当しているようだ。ヘッダファイルは次の通り。
※以下、ソースコードを引用
AGKeychain.h
@interface AGKeychain : NSObject {
}
+ (NSString *)getPasswordFromSecKeychainItemRef:(SecKeychainItemRef)item;
+ (BOOL)checkForExistanceOfKeychainItem:(NSString *)keychainItemName withItemKind:(NSString *)keychainItemKind forUsername:(NSString *)username;
+ (BOOL)modifyKeychainItem:(NSString *)keychainItemName withItemKind:(NSString *)keychainItemKind forUsername:(NSString *)username withNewPassword:(NSString *)newPassword;
+ (BOOL)deleteKeychainItem:(NSString *)keychainItemName withItemKind:(NSString *)keychainItemKind forUsername:(NSString *)username;
+ (BOOL)addKeychainItem:(NSString *)keychainItemName withItemKind:(NSString *)keychainItemKind forUsername:(NSString *)username withPassword:(NSString *)password;
+ (NSString *)getPasswordFromKeychainItem:(NSString *)keychainItemName withItemKind:(NSString *)keychainItemKind forUsername:(NSString *)username;
+ (NSString *)getPasswordFromSecKeychainItemRef:(SecKeychainItemRef)item;
@end
実装ファイルのインポート部分。Security.h を読み込んでいる。
AGKeychain.m
#import "AGKeychain.h"
#import
#import
@implementation AGKeychain
:
この中でみかける SecKeychain で始まる型や関数が Keychain Services の APIのようだ。
登録メソッドを見てみる。
+ (BOOL)addKeychainItem:(NSString *)keychainItemName withItemKind:(NSString *)keychainItemKind forUsername:(NSString *)username withPassword:(NSString *)password
{
SecKeychainAttribute attributes[3];
SecKeychainAttributeList list;
SecKeychainItemRef item;
OSStatus status;
attributes[0].tag = kSecAccountItemAttr;
attributes[0].data = (void *)[username UTF8String];
attributes[0].length = [username length];
attributes[1].tag = kSecDescriptionItemAttr;
attributes[1].data = (void *)[keychainItemKind UTF8String];
attributes[1].length = [keychainItemKind length];
attributes[2].tag = kSecLabelItemAttr;
attributes[2].data = (void *)[keychainItemName UTF8String];
attributes[2].length = [keychainItemName length];
list.count = 3;
list.attr = attributes;
status = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &list, [password length], [password UTF8String], NULL,NULL,&item);
if (status != 0) {
NSLog(@"Error creating new item: %d\n", (int)status);
}
return !status;
}
やっていることは多くない。
1. SecKeychainAttribute で属性を用意する
2. SecKeychainItemCreateFromContent( ) を呼び出す
簡単だ。Objective-C ベースでないのが残念(だからラッパーを作る人がいるわけだ)。
他の操作もコードは難しくない。
情報取得
result = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &list, &search);
if (result != noErr) {
NSLog (@"status %d from SecKeychainSearchCreateFromAttributes\n", result);
}
while (SecKeychainSearchCopyNext (search, &item) == noErr) {
CFRelease (item);
numberOfItemsFound++;
}
SecKeychainSearchCrateFromAttributes( ) で検索し、結果を SecKeychainSearchCopyNext() で回す。
削除
result = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &list, &search);
while (SecKeychainSearchCopyNext (search, &item) == noErr) {
numberOfItemsFound++;
}
if (numberOfItemsFound) {
status = SecKeychainItemDelete(item);
}
まず検索して SecKeyChainItemRef を取得し、それを使って削除する。
変更
result = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &list, &search);
SecKeychainSearchCopyNext (search, &item);
status = SecKeychainItemModifyContent(item, &list, [newPassword length], [newPassword UTF8String]);
削除同様、検索後に取得した SecKeyChainItemRef に対して変更をかける。
- - - -
操作自体は簡単なようだ。となると属性の意味や運用の仕方がポイントか。