KeychainAccessで​Keychainを​簡単に​扱おう

2 min read
keychain

Keychain

そもそも Keychain を使うメリットは何なのかという事になります。

似たような仕組みに UserDefaults があるのですが、何が違うのかを考えてみましょう。

UserDefaultsKeychain
アプリ削除データ消失消えない
データ保存先アプリ内Keychain
暗号化されないされる
データの共有不可条件を満たせば可能
他アプリからのデータ共有不可条件を満たせば可能
利用目的非セキュアなデータ保存パスコードなどの保存

データを共有するかどうかはおいといて、セキュアにデータを保存できるのが Keychain の強みとなります。アプリを削除してもデータが消えないというのは便利な気がしますね。

例えば Salmonia であれば Keychain に iksm_session を保存しておけばアプリを削除しても復活できるのは便利です。

KeychainAccess

Keychain にアクセスするのはめんどくさいのですが、KeychainAccessというライブラリを使えば簡単にアクセスできます。

が、これを使っても少し面倒な一面があるのでそれを更に便利にするための Extension を考えます。

import KeychainAccess
 
var keychain: Keychain {
    let server = "tkgstrator.work"
    return Keychain(server: server, protocolType: .https)
}
 
enum KeyType: String, CaseIterable {
    case iksmSession = "iksmSession"
    case sessionToken = "sessionToken"
}
 
extension Keychain {
    func setValue(value: String, forKey: KeyType) {
        try? keychain.set(value, key: forKey.rawValue)
    }
 
    func getValue(forKey: KeyType) -> String? {
        return try? keychain.get(forKey.rawValue)
    }
 
    func remove(forKey: KeyType) {
        try? keychain.set(nil, key: forKey.rawValue)
 
        // こっちでもいけるかも
        try? keychain.remove(forKey.rawValue)
    }
}

例えば上のような Extension を考えます。すると以下のようなコードでデータの読み書きができるようになります。

今回データの読み書きに Enum を使ったのは Typo によるキー指定のミスをなくすためです。キーの数が多ければミスも増えると思うので、Enum を使ったほうが良いかもしれません。

ただ、Enum が多いと書くのが面倒なので一つや二つくらいであれば直接指定でもいいのかも。

// データ保存
keychain.setValue(value: "IKSM SESSION", forKey: .iksmSession)
 
// データ取得
let iksmSession = keychain.getValue(forKey: .iksmSession)
 
// データ削除
keychain.remove(forKey: .iksmSession)

NSData や String の保存には対応しているっぽいのですが、Bool や Int の保存は現状できないっぽい感じでしょうか。まあ必要とあらば上手く変換したりすればいけるのではないかと思います。

@youtube