ずっと5月

3日坊主してます

KeyChain調査メモ

KeyChainとは?

UserDefaultと比較してセキュアに値を保存できる アプリを削除してもデータは残る(AppleIDに紐づく) 大量のデータ保存には向かない

使い方

(そのまま使うより神が作ったライブラリを使ったほうが楽らしい)

検索

任意の値に一致したデータが存在するか確認したいときは↓の関数 func SecItemCopyMatching(_ query: CFDictionary, _ result: UnsafeMutablePointer<CFTypeRef?>?) -> OSStatus 引数にクエリ(検索条件)と結果が見つかったときの結果の参照(ポインタ)を持つ

let search: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                             kSecAttrService as String: "service",// サービス名 必須じゃない。kSecAttrAccountと合わせてユニーク
                             kSecReturnAttributes as String: kCFBooleanTrue as Any, // kSecReturnAttributes:属性を返すか返さないか
                             kSecAttrAccount as String: "account1", // アカウント名 kSecAttrServiceと合わせてユニーク
                             kSecMatchLimit as String: kSecMatchLimitOne] as [String : Any] // 上限

// 保存データが存在するかの確認
let res = SecItemCopyMatching(search as CFDictionary, nil)

SecItemCopyMatchingの結果のステータスでこの辺は使う機会多いかも errSecItemNotFound:データが無かったとき errSecSuccess:エラーが無く成功(データが見つかったとき) errSecDuplicateItem:アイテムが重複していたとき 他↓参照 https://developer.apple.com/documentation/security/1542001-security_framework_result_codes

データの保存

// パスワード
let str = "password"
let data = str.data(using: .utf8)
guard let _data = data else {
        return false
}
let dic: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                          kSecValueData as String: _data,                // 保存したいもの
                          kSecAttrService as String: "service"]            // サービス名

var itemAddStatus: OSStatus? = itemAddStatus = SecItemAdd(dic as CFDictionary, nil)

削除

let dic: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                                  kSecAttrService as String: "service"]

if SecItemDelete(dic as CFDictionary) == errSecSuccess {
      // 削除成功したとき
} else {
      // 削除失敗したとき
}

その他メモ

保存するものの種類(パスワード、証明書、暗号鍵など)によって付属できる属性が変わる https://developer.apple.com/documentation/security/keychain_services#//apple_ref/doc/uid/TP30000898-CH4g-SW18

kSecAttrAccountとkSecAttrServiceの値を使ってユニークなデータとして保存している。kSecAttrServiceが違えばkSecAttrAccountが同じでもOK kSecAttrService は必須ではなくてkSecAttrAccount だけで運用可。 *その場合は同じ kSecAttrAccount の値は複数登録できない

参考

https://qiita.com/ayutaso/items/960e1b1f553e53ca60f4 https://ameblo.jp/xcc/entry-10813323465.html http://cocoadays.blogspot.com/2011/02/ios-keychain-services.html https://qiita.com/mario7/items/11f06502a022c01cfbb5