まず、キーチェーンによる秘密の保護に関する WWDC 2013 セッションを見てきました。基本的なパスコード ストアを実行したいと考えています。ビデオ全体を見ましたが、ビデオの最初の 10 分間で必要なものを見つけました。簡単に思えますが、データのエンコードと取得がどのように機能するのか完全には理解していません。
問題: secItemCopyMatching の後、NSString に変換する前に、NSData オブジェクトをチェックして nil でないことを確認します。問題は、それが常に nil であることです。以下は、キーチェーンのエントリまたは更新を保存する方法と、それを取得する方法です。ヘルプと説明をいただければ幸いです。
更新 (編集): Fruity Geek、返信ありがとうございます。__bridge を使用して以下のコードを更新しました。私の問題は、パスワードを正しく保存および取得していますか? 両方とも間違っているのでしょうか、それともどちらか一方だけですか? 私の NSData インスタンスは常に nil です。リターン コードを確認しており、SecItemAdd と SecItemUpdate (キーチェーン エントリが存在する場合) が正しく機能しています。保存されているデータ (パスコード) の文字列値を取得して、ユーザーが入力したパスコードと比較できないようです。助けてくれたみんなに感謝します。これが私が今していることです:
更新#2:(Fruity Geekの回答と最終作業バージョンで編集。私の編集には、以下のコードへの変更のみが含まれます。)
キーチェーン エントリを設定します。
NSData *secret = [_backupPassword dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: twServiceName,
(__bridge id)kSecAttrAccount: twAccountName,
(__bridge id)kSecValueData: secret,
};
OSStatus status =
SecItemAdd((__bridge CFDictionaryRef)query, NULL);
if (status == errSecDuplicateItem) {
// this item exists in the keychain already, update it
query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: twServiceName,
(__bridge id)kSecAttrAccount: twAccountName,
};
NSDictionary *changes = @{
(__bridge id)kSecValueData: secret,
};
status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)changes);
}
キーチェーンからパスワードを取得します。
NSDictionary *query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: twServiceName,
(__bridge id)kSecAttrAccount: twAccountName,
(__bridge id)kSecReturnData: @YES,
};
NSData *data = NULL;
CFTypeRef dataTypeRef = (__bridge CFTypeRef)data;
OSStatus status =
SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataTypeRef);
NSData *data = (__bridge NSData *)dataTypeRef;
NSString *passcode = @"none";
if (status == errSecSuccess) {
// we found a keychain entry, set the passcode
if (data)
passcode = [NSString stringWithUTF8String:[data bytes]];
}
twServiceName と twAccountName は静的 NSString です。
私が言ったように、私は __bridge または CFTypeRef で何をしているのかよくわかりません。私はリンゴのドキュメント、ここや他のサイトの多数の投稿を調べましたが、キーチェーンとこれらの用語は私にとってまったく新しいものであり、まだ理解しようとしています. ここの誰かが私の誤りを指摘し、理解を助けてくれることを願っています。助けてくれてありがとう。
iOS 7 / Xcode 5