ExKeychain

Elixir bindings to macOS Keychain Services via Security.framework.

Uses Rustler NIFs backed by the security-framework Rust crate (146M+ downloads, used by reqwest and rustls).

Installation

def deps do
  [{:ex_keychain, "~> 0.1.0"}]
end

Requires Rust toolchain (rustup). macOS only.

Usage

# Store a password
:ok = ExKeychain.set("my-app", "user@example.com", "s3cret")

# Retrieve it
{:ok, "s3cret"} = ExKeychain.get("my-app", "user@example.com")

# Check existence without triggering access dialogs
true = ExKeychain.exists?("my-app", "user@example.com")

# List all accounts for a service
["user@example.com"] = ExKeychain.list("my-app")

# Delete
:ok = ExKeychain.delete("my-app", "user@example.com")

How It Works

All keychain operations go through Apple's Security.framework C API (SecItemAdd, SecItemCopyMatching, SecItemUpdate, SecItemDelete). The Rust layer provides safe wrappers and handles CoreFoundation type conversion. Rustler handles the Erlang NIF machinery.

All NIF functions are scheduled on dirty I/O schedulers since keychain operations involve IPC with the securityd daemon.

Code Signing

Some keychain operations (especially on the system keychain or with access control lists) require code signing. For development, a self-signed certificate works. For distribution, use a proper Developer ID certificate.

License

MIT