KeychainHelper

コード(iOS)

使用するには型を合わせる必要があります。

バージョン1

バージョン2

✅ 使い方

メソッド用途使用例
save(data:service:account:)トークンを保存KeychainHelper.save(data, service: "com.example.app", account: "token")
load(service:account:)トークンを読み出すKeychainHelper.load(service: "com.example.app", account: "token")
delete(service:account:)特定のトークンを削除KeychainHelper.delete(service: "com.example.app", account: "token")
exists(service:account:)トークンがあるか確認if KeychainHelper.exists(service: "com.example.app", account: "token") { ... }
clearAll()全削除(開発用・慎重に)KeychainHelper.clearAll()

✅ 実用例(ログアウト時や再取得時)

🔹Keychain の「安全な上書き(更新)」方法

Keychain には本来「上書き」というメソッドはありません。
代わりに Apple が推奨しているのは SecItemUpdate を使う方法です。

 KeychainHelper にこの更新メソッドを追加する場合は、こうなります👇

 service と account について

Keychain の保存は「service」と「account」という2つのキーで識別されます。

  • service
  • account

つまり、同じ service 内に複数の account を持てる仕組みになっています。
👉 任意の文字列でOKですが、「後から見てわかりやすい」命名にすると管理が楽です。

命名のベストプラクティス

  • service → アプリ固有の文字列(com.name.weatherapp
  • account → 保存するデータの種類(authToken / refreshToken

これで一目見て「どのアプリの何のデータか」がわかるようになります。

CFDictionary

CFDictionary とは?

  • Core Foundation フレームワークの 辞書型(連想配列)のことです。
  • Swift や Objective-C から使うときは、通常の Dictionary<String, Any> を as CFDictionary でキャストして渡せば使えます。
  • なぜ必要かというと、Keychain の低レベル API (SecItemAddSecItemCopyMatching, etc.) は Core Foundation 時代の C API をベースに作られているからです。

例で分解すると

ここでやっていることは:

  1. Swift の辞書 query を作る
  2. SecItemAdd は C の関数なので Swift の Dictionary をそのまま渡せない
    → そこで as CFDictionary をつけて「Core Foundation 辞書」に変換している。

参考:SecItemAdd のシグネチャ

  • func SecItemAdd(_ attributes: CFDictionary, _ result: UnsafeMutablePointer?) -> OSStatus
  • func SecItemAdd(_ attributes: CFDictionary, _ result: UnsafeMutablePointer?) -> OSStatus
  • 第二引数: UnsafeMutablePointer<CFTypeRef?>?(結果を受け取るポインタ、今回は不要なので nil

**CFDictionary は「Keychain API が要求する辞書の型」**で、Swift の辞書をそのままキャストして渡しているだけ。

macOS互換

macOSでも問題なく使用できますか?

基本的にはそのまま動作しますSecurityフレームワークと使用しているAPI(SecItemAddSecItemCopyMatchingSecItemDelete)はすべてmacOSでも利用可能です。

ただし、いくつか注意すべき点があります。

✅ 問題なく動く部分

  • kSecClassGenericPassword をはじめ、使用しているすべての属性キーはmacOSでサポートされています
  • SecItemAdd / CopyMatching / Delete のAPIシグネチャも同一です

⚠️ macOS固有の注意点

1. kSecAttrAccessible の挙動の違い

コードに kSecAttrAccessible の指定がないため、プラットフォームのデフォルト値に依存します。macOSではiOSと異なるデフォルト動作をすることがあるため、明示的に指定することを推奨します。

2. Entitlement(権限設定)

macOSのサンドボックスアプリでは、Keychain Sharing Entitlementが必要な場合があります。Xcodeの Signing & Capabilities で確認してください。

3. clearAll() のリスク

macOSでは(特に非サンドボックス環境で)Keychainがアプリ間で共有される場合があります。kSecClass のみでの全削除は他アプリのデータにも影響する可能性があるため、開発・デバッグ専用であっても注意が必要です。

4. 非サンドボックスアプリでのアクセス確認ダイアログ

非サンドボックスのmacOSアプリでは、Keychainアイテムへの初回アクセス時にユーザーへの許可ダイアログが表示されることがあります。

まとめ

観点状況
API互換性✅ 問題なし
サンドボックスアプリ✅ ほぼそのまま動作
kSecAttrAccessible⚠️ 明示指定を推奨
clearAll()⚠️ macOSでは要注意
非サンドボックスアプリ⚠️ 許可ダイアログが出る場合あり

Catalyst(iPad→Mac変換)や SwiftUI の macOS ターゲットであれば、特に kSecAttrAccessible の明示指定と clearAll() の修正だけ対応しておけば、安全に流用できます。

macOS対応のIntバージョン

コメント

タイトルとURLをコピーしました