キーチェーンアイテムをユニークにする理由(iOSの場合)


104

私の質問は、iOS(iPhone、iPadなど)のキーチェーンに関係します。Mac OS Xでのキーチェーンの実装は、同じ答えで同じ質問を引き起こすと思います(しかし、確信はありません)。


iOSでは、5種類(クラス)のキーチェーンアイテムを提供しています。kSecClassタイプを判別するには、キーに対してこれらの5つの値のいずれかを選択する必要があります。

kSecClassGenericPassword  used to store a generic password
kSecClassInternetPassword used to store an internet password
kSecClassCertificate      used to store a certificate
kSecClassKey              used to store a kryptographic key
kSecClassIdentity         used to store an identity (certificate + private key)

リンゴのドキュメント、ブログやフォーラム・エントリーを読み取る長い時間の後、私はタイプのキーチェーン項目があることが分かったkSecClassGenericPassword属性からそのユニークさを取得しkSecAttrAccessGroupkSecAttrAccountそしてkSecAttrService

リクエスト1の3つの属性がリクエスト2の属性と同じである場合、他の属性に関係なく、同じ汎用パスワードキーチェーンアイテムを受け取ります。この属性の1つ(または2つまたはすべて)がその値を変更すると、異なるアイテムが取得されます。

ただしkSecAttrService、タイプのアイテムでのみ使用できるためkSecClassGenericPassword、他のタイプのアイテムの「一意のキー」の一部にすることはできません。また、キーチェーンアイテムを一意に決定する属性を明確に指摘するドキュメントはないようです。

「GenericKeychain」の「KeychainItemWrapper」クラスのサンプルコードでは、属性kSecAttrGenericを使用してアイテムを一意にしていますが、これはバグです。この例の2つのエントリは、それらkSecAttrAccessGroupが異なるため(1つはアクセスグループセットを持ち、もう1つは解放できるため)、2つの異なるエントリとしてのみ格納されます。Appleを使用して、アクセスグループなしで2番目のパスワードを追加しようとすると、KeychainItemWrapper失敗します。

だから、私の質問に答えてください:

  • それは、真実であることの組み合わせkSecAttrAccessGroupkSecAttrAccountおよびkSecAttrServicekSecClassがあるキーチェーン項目の「一意のキーは」ありますかkSecClassGenericPassword
  • その場合は、どの属性がキーチェーン項目がユニークなのkSecClassではありませんかkSecClassGenericPassword

1
これについてのブログエントリがあります。
bobobobo 2013年

回答:


179

主キーは次のとおりです(Appleのオープンソースファイルから派生。Schema.m4KeySchema.m4SecItem.cpp参照)。

  • クラスのキーチェーンアイテムのkSecClassGenericPassword場合、主キーはkSecAttrAccountおよびの組み合わせです kSecAttrService
  • クラスのキーチェーン項目に対してkSecClassInternetPassword、主キーの組み合わせであるkSecAttrAccountkSecAttrSecurityDomainkSecAttrServerkSecAttrProtocolkSecAttrAuthenticationTypekSecAttrPortおよびkSecAttrPath
  • クラスのキーチェーン項目に対してkSecClassCertificate、主キーの組み合わせであるkSecAttrCertificateTypekSecAttrIssuerkSecAttrSerialNumber
  • クラスのキーチェーン項目に対してkSecClassKey、主キーの組み合わせであるkSecAttrApplicationLabelkSecAttrApplicationTagkSecAttrKeyTypekSecAttrKeySizeInBitskSecAttrEffectiveKeySizeまだSecItemによって露出されず、作成者、開始日と終了日。
  • クラスのキーチェーンアイテムのkSecClassIdentity場合、オープンソースファイルの主キーフィールドに関する情報は見つかりませんでしたが、IDは秘密キーと証明書の組み合わせであるため、主キーは主キーの組み合わせであると想定していますkSecClassKeyおよびのフィールドkSecClassCertificate

各キーチェーンアイテムはキーチェーンアクセスグループに属しているため、キーチェーンアクセスグループ(フィールドkSecAttrAccessGroup)は、これらすべての主キーに追加されたフィールドのように感じられます。


本当に良い答えのように聞こえます!ありがとうございました!確認します。他のユーザーからのコメントが追加されるまで1〜2日待ちたいのですが、賞金の+50ポイントのホットな候補者です。
HubertSchölnast2012

3
正解です。私は数日間、証明書と秘密鍵用の汎用キーチェーンラッパーの実装に取り​​組んでいます。これは、文字列の資格情報(ユーザー名/パスワード)のみを格納するAppleのサンプルコードとは大きく異なります。ただし、に設定しkSecClasskSecClassCertificate場合kSecClassKey、またはキーチェーンがエントリ(value)がすでに格納されているかどうかもチェックすることを確認しました。これにより、同じ証明書またはキーを2回追加することを防止できます。またkSecAttrApplicationTag、キーに別のキーを指定すると(上記の投稿に関して一意である必要があります)、失敗します。
Chris

1
kSecClass属性をテーブル名と考え、上記の指定された値をprimary keyそれぞれのテーブルの単なるものと考えると役立つ場合があります。
bobobobo 2013年

2
kSecAttrAccountand のセマンティクスは何kSecAttrServiceですか?-またはプログラマーは、彼女が決定するセマンティクスを選択できますか?
wcochran 2014年

1
kSecAttrServiceサービスkSecAttrAccountを保存するためのもので、アカウント名を保存するためのものです。あなたはそれらに異なるものを保存することができますが、それは混乱するかもしれません。
Tammo Freese、2014

9

先日(iOS 7.1で)この質問に関連するバグに遭遇しました。私が使っていたSecItemCopyMatching読むためkSecClassGenericPasswordのアイテムを、それが戻って保持errSecItemNotFoundにもかかわらず(-25300)をkSecAttrAccessGroupkSecAttrAccountそしてkSecAttrService全てのキーチェーンの項目をマッチングされました。

結局、私kSecAttrAccessibleはそれが一致しないことを理解しました。キーチェーンの値はpdmn = dk(kSecAttrAccessibleAlways)を保持していましたが、私はを使用していましたkSecAttrAccessibleWhenUnlocked

もちろん、この値は、のために最初の場所で必要とされていないSecItemCopyMatching、しかしOSStatusではなかったerrSecParamにもerrSecBadReqちょうどerrSecItemNotFound(-25300)それは少しトリッキー見つけるために作られています。

以下のためにSecItemUpdate、私は同じ問題を経験したが、この方法でも、それを利用してきたkSecAttrAccessible中でquery、パラメータは動作しませんでした。この属性を完全に削除しただけで修正されました。

このコメントがあなたにとって一部の貴重なデバッグの瞬間を保存してくれることを願っています。


4

@Tammo Freeseの回答は正しいようです(ただし、すべての主キーについて言及しているわけではありません)。ドキュメントでいくつかの証拠を探していました。ついに見つけた:

シークレットの各クラスの主キーについて言及しているAppleドキュメント(以下の引用):

システムは、そのキーチェーンに同じ複合主キーの同じセットを持つ同じクラスのアイテムがすでにある場合、そのキーチェーンのアイテムは重複していると見なします。キーチェーンアイテムの各クラスには、主キーの異なるセットがありますが、いくつかの属性はすべてのクラスで共通に使用されます。特に、該当する場合、kSecAttrSynchronizableとkSecAttrAccessGroupは主キーのセットの一部です。追加のクラスごとの主キーを以下に示します。

  • 汎用パスワードの場合、主キーにはkSecAttrAccountおよびkSecAttrServiceが含まれます
  • インターネットパスワードの場合、主キーには、kSecAttrAccount、kSecAttrSecurityDomain、kSecAttrServer、kSecAttrProtocol、kSecAttrAuthenticationType、kSecAttrPort、およびkSecAttrPathが含まれます。
  • 証明書の場合、主キーにはkSecAttrCertificateType、kSecAttrIssuer、およびkSecAttrSerialNumberが含まれます。
  • キーアイテムの場合、主キーには、kSecAttrKeyClass、kSecAttrKeyType、kSecAttrApplicationLabel、kSecAttrApplicationTag、kSecAttrKeySizeInBits、およびkSecAttrEffectiveKeySizeが含まれます。
  • 証明書と秘密鍵がバンドルされたIDアイテムの場合、主キーは証明書の場合と同じです。秘密鍵は複数回認証される可能性があるため、証明書の一意性がアイデンティティの一意性を決定します。

このリンクで質問に答えることができますが、回答の重要な部分をここに含め、参照用のリンクを提供することをお勧めします。リンクされたページが変更されると、リンクのみの回答が無効になる可能性があります。- レビューより
pwc

この場合、リンク全体をコピーすることを意味しましたが、同意しました。
JulianKról18年

0

キーチェーンアイテムの一意性に関するもう1つの便利な情報を以下に示しますこれは、このAppleドキュメントページの「検索可能性の確認」セクションにあります

後でアイテムを見つけることができるように、その属性の知識を使用します。この例では、サーバーとアカウントがアイテムの際立った特徴です。定数属性(ここではサーバー)の場合、ルックアップ中に同じ値を使用します。対照的に、実行時にユーザーが提供する値を保持するため、アカウント属性は動的です。アプリがさまざまな属性(同じサーバー上の異なるアカウントのパスワードなど)を持つ同様のアイテムを追加しない限り、これらの動的属性を検索パラメーターとして省略し、代わりにアイテムと共に取得できます。その結果、パスワードを検索すると、対応するユーザー名も取得されます。

アプリがさまざまな動的属性を持つ項目を追加する場合は、取得時にそれらの中から選択する方法が必要になります。1つのオプションは、アイテムに関する情報を別の方法で記録することです。たとえば、Core Dataモデルでユーザーのレコードを保持している場合、キーチェーンサービスを使用してパスワードフィールドを保存した後、そこにユーザー名を保存します。その後、データモデルから取得したユーザー名を使用して、パスワードの検索を条件付けします。

他の場合では、さらに属性を追加してアイテムをさらに特徴付けることが理にかなっています。たとえばkSecAttrLabel、元の追加クエリに属性を含め、特定の目的のためにアイテムをマークする文字列を提供できます。その後、この属性を使用して、後で検索を絞り込むことができます。

kSecClassInternetPassword例ではクラスのアイテムが使用されましたが、次のように書かれています。

キーチェーンサービスは、関連するkSecClassGenericPasswordアイテムクラスも提供します。汎用パスワードは、ほとんどの点でインターネットパスワードに似ていますが、リモートアクセスに固有の特定の属性がありません(たとえば、kSecAttrServer属性がありません)。これらの追加の属性が必要ない場合は、代わりに汎用パスワードを使用してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.