cgo-free Go bindings for Apple frameworks, built on purego.
Binaries can be built with CGO_ENABLED=0 and cross-compiled for macOS from any OS.
This is an unofficial project and is not affiliated with Apple. It supports macOS only; other platforms fail to compile.
| Package | Framework |
|---|---|
security |
Keychain Services (SecItemAdd, SecItemCopyMatching, SecItemUpdate, SecItemDelete, SecAccessControl) |
localauthentication |
LocalAuthentication (LAContext) for Touch ID and device password prompts |
security/legacy |
Deprecated APIs of the file-based keychain (SecKeychain, SecAccess, SecTrustedApplication) |
import "github.com/yokonao/appleframeworks/security"
_, err := security.Add(security.Attrs{
security.Class: security.ClassGenericPassword,
security.AttrService: "com.example.app",
security.AttrAccount: "token",
security.ValueData: []byte("secret"),
})
data, err := security.CopyMatching(security.Attrs{
security.Class: security.ClassGenericPassword,
security.AttrService: "com.example.app",
security.AttrAccount: "token",
security.ReturnData: true,
security.MatchLimit: security.MatchLimitOne,
})
if errors.Is(err, security.ErrItemNotFound) {
// ...
}
secret := data.([]byte)The API mirrors the C API: queries are dictionaries keyed by the same constants, and results take the shape the query asks for. See the package documentation for how values are converted between Go and CoreFoundation.
Keychain constants hold their symbol names and are resolved at run time. A constant this
module does not define yet can be used as security.Key("kSecAttrXxx"), and one
missing from the running macOS returns security.ErrUnavailable.
import la "github.com/yokonao/appleframeworks/localauthentication"
c, err := la.NewContext()
err = c.EvaluatePolicy(la.PolicyDeviceOwnerAuthenticationWithBiometrics, "unlock the vault")
if errors.Is(err, la.ErrUserCancel) {
// ...
}Objects of one framework are passed to another through their CFTypeRef method, such as
an LAContext to reuse its authentication for Keychain items:
data, err := security.CopyMatching(security.Attrs{
// ...
security.UseAuthenticationContext: c,
})Keychain items with AttrAccessControl, and UseAuthenticationContext, work only in the
data protection keychain, which requires a signed binary with the keychain-access-groups
entitlement. Ad-hoc signed binaries can use the file-based keychain through security/legacy.
macOS 12 Monterey or later, the oldest that Go 1.26 runs on. Every function, class and
method this module binds is available there. These constants need a newer macOS and
return ErrUnavailable on older ones:
| Constant | macOS |
|---|---|
MatchHostOrSubdomainOfHost |
15.0 |
go test ./internal/availability checks this against the installed SDK, so a newly bound
symbol that raises the requirement fails the test. It cannot detect symbols Apple removes,
such as the deprecated ones in security/legacy.
go test ./...
golangci-lint run
golangci-lint fmtThe constants in security/symbols.go and security/errors.go are generated from
the headers of the installed macOS SDK:
go generate ./...Tests add and remove items in the login keychain. LA_MANUAL=1 go test -run Manual ./localauthentication shows a Touch ID prompt.