A tiny, type-safe Keychain wrapper for Swift. Store secrets behind phantom-typed keys so the compiler — not you — keeps track of what type lives at each key.
The Keychain API is stringly-typed: you write Data, you read Data, and you're
left to remember what was supposed to live at each key. PhantomKeychain gives you
KeychainKey<Value> — a key that carries its value's type at compile time:
let token = KeychainKey<String>(name: "auth_token")
store.set("abc", forKey: token) // ✅ String in
let value: String? = store.get(forKey: token) // ✅ String out, no casting
store.set(true, forKey: token) // ❌ won't compile — `token` is a String keySwift Package Manager — add the dependency to your Package.swift:
.package(url: "https://github.com/hamsternik/PhantomKeychain.git", from: "0.1.0"),then add PhantomKeychain to your target:
.product(name: "PhantomKeychain", package: "PhantomKeychain"),import PhantomKeychain
let store: KeychainStore = KeychainStoreLive(keyPrefix: "com.yourapp.")
let apiToken = KeychainKey<String>(name: "api_token")
store.set("s3cr3t", forKey: apiToken) // -> Bool
let token = store.get(forKey: apiToken) // -> String?
store.remove(by: apiToken) // -> Bool
store.clear() // wipe everything under the prefixString, Data, and Bool are storable out of the box. Conform your own types to
KeychainStorable (a var keychainData: Data getter plus an init?(keychainData:))
to store them too.
Swap in KeychainStoreInMemory — a thread-safe, Keychain-free double with identical
behavior — so your tests never touch the system Keychain:
let store: KeychainStore = KeychainStoreInMemory()- Access: items use
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly— readable after first unlock, never synced to iCloud or restored to another device. - Prefix: keys are namespaced by
keyPrefix. Pass your own to isolate your app's items from anything else in the Keychain. - Backing:
0.1.0is built on KeychainSwift.0.2.0will drop it for a zero-dependencySecurity/SecItemimplementation — with the same public API.
- Publish a GitHub Release with notes for
0.2.0(skipped for0.1.0). - Register the package on Swift Package Index for discoverability.
- Add an example project demonstrating real-world integration of the library in an app.
- Expand CI to a full test matrix across every supported platform/OS/device (currently only
swift teston the macOS host). Reference: KeychainAccesstest.yml— matrix over macOS runners × Xcode versions × simulator OS versions × device models, withxcodebuild testper destination.
- Swift 5.9+
- iOS 16+ · macOS 13+ · watchOS 9+
MIT © 2026 Mykyta Khomitsevych