0Pricing
Swift Academy · レッスン

Keychainのアクセス制御

生体認証やデバイスのロック解除を必須にして項目を保護します。

「Keychainのアクセス制御」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

シークレットを読み取り可能にするタイミングの制御

シークレットの保存は仕事の半分にすぎません。いつ読み取れるかも制御する必要があります。Keychainにはアクセシビリティクラスとアクセス制御フラグがあり、デバイスのロック解除、パスコード、または生体認証によってアイテムへのアクセスを制限できます。これにより、デバイスを紛失した場合にもデータを保護できます。

import Security
// Two layers of control:
//   kSecAttrAccessible  -> when readable (lock state)
//   SecAccessControl    -> user presence / biometrics

kSecAttrAccessibleキー

kSecAttrAccessibleは追加時にアクセシビリティクラスを設定します。アイテムを常に利用可能にするか、初回のロック解除後のみ利用可能にするか、デバイスのロック解除中のみ利用可能にするかを決定します。機能が許容する範囲で最も厳格なレベルを選んでください。

import Security
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "user",
    kSecValueData as String: Data("secret".utf8),
    kSecAttrAccessible as String:
        kSecAttrAccessibleWhenUnlocked
]
_ = query

WhenUnlocked

kSecAttrAccessibleWhenUnlockedを指定すると、デバイスのロック解除中のみアイテムを読み取れます。ロック中に実行されるバックグラウンドタスクからはアクセスできません。ほとんどのセッショントークンに適した妥当なデフォルトです。

import Security
// Readable only while unlocked; blocked when locked.
let level = kSecAttrAccessibleWhenUnlocked
_ = level

AfterFirstUnlock

kSecAttrAccessibleAfterFirstUnlockを指定すると、起動後の初回ロック解除から次の再起動まで、後で再びロックされてもアイテムを読み取れます。プッシュ処理用のトークンなど、バックグラウンドプロセスが必要とするシークレットに使用してください。

import Security
// Available after the first unlock post-boot,
// including while subsequently locked.
let level = kSecAttrAccessibleAfterFirstUnlock
_ = level

ThisDeviceOnlyバリアント

各アクセシビリティクラスには...ThisDeviceOnly形式があります。これらのアイテムは暗号化バックアップから除外され、新しいデバイスに移行されることもありません。このハードウェアから決して持ち出したくないキーに使用してください。

import Security
// Never backed up, never migrated:
let local = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
_ = local

パスコード設定時

kSecAttrAccessibleWhenPasscodeSetThisDeviceOnlyを指定すると、ユーザーがパスコードを設定している場合にのみアイテムが保存され、パスコードを削除するとアイテムも削除されます。シークレットが常にパスコードで保護されることを保証できます。

import Security
let level =
    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
// Item vanishes if the user disables their passcode.
_ = level

ユーザーの存在確認に使うSecAccessControl

ロック状態に加えて、SecAccessControlCreateWithFlagsを使うと、読み取り時に生体認証またはパスコードによるユーザー認証を必須にするポリシーを作成できます。これはkSecAttrAccessControlを通じて、アクセシビリティキーの代わりに、またはアクセシビリティキーと併用して設定します。

import Security
func makeControl() -> SecAccessControl? {
    return SecAccessControlCreateWithFlags(
        nil,
        kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
        .userPresence,
        nil)
}

アクセス制御フラグ

フラグで要件を細かく指定できます。.userPresenceは生体認証またはパスコードへのフォールバックを許可し、.biometryCurrentSetは登録済みの指紋や顔が変更されるとアイテムを無効にし、.devicePasscodeはパスコードの入力を必須にします。組み合わせてセキュリティ要件を表現してください。

import Security
// .userPresence        -> biometric OR passcode
// .biometryAny         -> any enrolled biometric
// .biometryCurrentSet  -> invalidate on biometric change
// .devicePasscode      -> passcode only
let flags: SecAccessControlCreateFlags = [.userPresence]
_ = flags

保護されたアイテムの追加

生体認証で保護するシークレットを保存するには、SecAccessControlオブジェクトをkSecAttrAccessControlに設定します。後で読み取ると、データが返される前にユーザー認証が求められます。

import Security
func saveProtected(_ data: Data, account: String,
                   control: SecAccessControl) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account,
        kSecValueData as String: data,
        kSecAttrAccessControl as String: control]
    return SecItemAdd(query as CFDictionary, nil)
        == errSecSuccess
}

読み取り時のユーザー認証

保護されたアイテムを読み取ると、認証UIが自動的に表示されます。kSecUseOperationPromptを使って理由の文字列を指定すれば、なぜアクセスが必要なのかをプロンプトで説明できます。読み取りは、ユーザーが認証するかキャンセルするまでブロックされます。

import Security
func readProtected(account: String) -> Data? {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account,
        kSecReturnData as String: true,
        kSecUseOperationPrompt as String:
            String(localized: "Unlock your saved key")]
    var out: CFTypeRef?
    return SecItemCopyMatching(query as CFDictionary,
        &out) == errSecSuccess ? out as? Data : nil
}

適切なレベルの選択

リスクに応じてポリシーを選択してください。

  • バックグラウンドで使用するセッショントークン:AfterFirstUnlock。
  • UIからのみ使用するトークン:WhenUnlocked。
  • 価値の高いシークレット:.userPresenceを指定したSecAccessControlとThisDeviceOnlyクラス。

厳格にするほど安全ですが、バックグラウンドアクセスができなくなります。両方のバランスを取ってください。

import Security
// High-value: biometric-gated, device-bound, no backup
let control = SecAccessControlCreateWithFlags(
    nil,
    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
    .userPresence, nil)
_ = control

クイックチェック

バックグラウンドで必要になるシークレットに適したアクセシビリティクラスを思い出してください。

まとめ

Keychainアイテムへのアクセス制限について学びました。

  • kSecAttrAccessibleでロック状態に応じた利用可能性を設定します。WhenUnlocked、AfterFirstUnlock、およびバックアップを除外する...ThisDeviceOnlyバリアントがあります。
  • WhenPasscodeSetThisDeviceOnlyを使うと、アイテムをパスコードの設定と結び付けられます。
  • .userPresenceや.biometryCurrentSetなどのフラグを付けたSecAccessControlにより、読み取り時の認証を必須にできます。
  • アクセス方法を妨げない範囲で、最も厳格なレベルを選択してください。

よくある質問

「Keychainのアクセス制御」レッスンは無料ですか?

はい。「Keychainのアクセス制御」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「Keychainのアクセス制御」で何を学びますか?

生体認証やデバイスのロック解除を必須にして項目を保護します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「Keychainのアクセス制御」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Keychainへの秘密情報の保存
  2. Keychainのアクセス制御
  3. 生体認証
  4. データ保護と暗号化
← Swift Academyに戻る