ラベル Keychain の投稿を表示しています。 すべての投稿を表示
ラベル Keychain の投稿を表示しています。 すべての投稿を表示

2011年4月23日土曜日

KeychainItemWrapper を改造して、複数の Keychain Item に同時にアクセス出来るようにしてみた

※2011/04/23現在での情報です。以下の問題は全て Apple に対して報告いたしましたので、ひょっとしたら将来的に修正されるかもしれません。


現在の仕事にて課金情報を安全にアプリケーション内に保存したいということになり、それならばということで iOS に最初から用意されている Security.framework を使って Keychain 領域に情報を保存するアプリを作ることにしました。この Security.framework は全てC言語にて実装されており、そのまま使うと非常に取っつきづらいです。そこで、 Apple がサンプルコードとして提供している GenericKeychain プロジェクトKeychainItemWrapper クラスを使って Keychain 領域にアクセスすることにしました。

最初は問題ないように見えたのですが、実はこの KeychainItemWrapper クラス、Version 1.2には深刻なバグがあります。それは、複数の KeychainItemWrapper クラスのインスタンスを使って複数の識別子を持った情報を保存しようとすると、同時に一種類しか保存できなくなる(二つめを保存しようとするとステータスコード25299が返却されて保存できなくなる)というものです。

原因を調査した結果、以下のページに記載されている内容が問題だとわかりました。
http://useyourloaf.com/blog/2010/3/29/simple-iphone-keychain-access.html
The combination of the final two attributes kSecAttrAccount and kSecAttrService should be set to something unique for this keychain. In this example I set the service name to a static string and reuse the identifier as the account name.
サンプルで提供されている KeychainItemWrapper クラスにはこれらの一意となるキーが指定されておらず、単に検索用の kSecAttrGeneric だけが指定されていたため、一意キーの指定がおかしくなって二つ目の Keychain アイテムが保存できなくなっていた、というわけです。

そこでこちらの問題を修正した KeychainItemWrapper クラスをご用意しました。
https://gist.github.com/938375

ライセンスは元となるAppleのオープンソースライセンスに準拠します。改変・再配布・利用すべて自由ですが、その際ソースコードの最上部にあるAppleのライセンス条項コードは絶対に改変しないでください。Apple先生に何か言われても私は知りませんよ><


■修正版 KeychainItemWrapper の使い方

基本的には通常の KeychainItemWrapper と何ら変わりません。
// インスタンスを作る
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"com.akisute.keychain.KeychainTestApp.item1"
serviceName:@"com.akisute.KeychainTestApp"
accessGroup:nil];

// 値を保存する
// いったんresetKeychainItemしているのはmyValueがnilのとき保存されているデータを削除したいから
// 基本的に値(kSecValueData)として保存できるのはUTF-8のNSStringのみです。内部的にNSDataに変換されてKeychainに保存されます。
// それ以外の情報を保存したい場合はすみませんが未対応です>< Base64文字列にするとかJSON文字列にするとか工夫して回避してください><
NSString *myValue = @"abesi";
[wrapper resetKeychainItem];
[wrapper setObject:myValue forKey:(id)kSecValueData];

// 値を取り出す
NSString *resultValue = [wrapper objectForKey:(id)kSecValueData];
NSLog(@"resultvalue = %@", resultValue);

2009年6月26日金曜日

Keychain Accessから秘密鍵を書き出すときに、「エラーが発生しました。項目を読み込めません。」と表示されたときの対処法

iPhone開発にはAppleが発行する証明書が必要になるため、なにかとKeychain Accessのお世話になることが多いです。特に、複数台のMacで開発を行っている場合は、証明書を認証するための秘密鍵を複数台のMacにインストールする必要があります。
このとき、最初のMacから別のMacに秘密鍵を移すために、Keychain Accessから秘密鍵を書き出しする必要があるのですが、書き出した秘密鍵を取り込もうとすると「エラーが発生しました。項目を読み込めません。」とエラーが出て取り込みが出来ないケースがあります。


こんなダイアログです。

このダイアログが出てしまったときの対処法をまとめてみました。


■結論から言うと
このダイアログが出てしまったときは、秘密鍵の書き出し方を間違っています。


この「すべての項目」画面から鍵を書き出してしまうと、書き出しには成功しますが読み込むときに100%失敗してしまいます。


こちらの「証明書」画面から証明書の階層を開き、鍵を書き出すと、正常に読み込むことが出来ます。