Skip to content

About

cgo-free Go bindings for Apple frameworks

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

appleframeworks

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.

Packages

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)

Usage

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.

Supported macOS

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.

Development

go test ./...
golangci-lint run
golangci-lint fmt

The 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.

About

cgo-free Go bindings for Apple frameworks

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages