Golang keychain package for iOS and macOS
Find a file
2025-01-23 19:18:43 -05:00
.github/workflows Upgrade to go 1.23 (#110) 2025-01-07 11:27:24 -05:00
bind test against supported go versions (#74) 2021-11-19 13:19:46 -05:00
bindtest test against supported go versions (#74) 2021-11-19 13:19:46 -05:00
ios Revert "Update for cgo changes in go 1.10" 2018-02-26 11:16:11 -05:00
secretservice Upgrade to go 1.23 (#110) 2025-01-07 11:27:24 -05:00
.gitignore clean up go.mod manifest and update tool deps (#67) 2020-11-20 20:30:09 -05:00
.golangci.yml Upgrade to go 1.23 (#110) 2025-01-07 11:27:24 -05:00
corefoundation.go Add support for internet password items (#95) 2023-05-18 14:58:16 -04:00
datetime.go Upgrade to go 1.23 (#110) 2025-01-07 11:27:24 -05:00
datetime_test.go test against supported go versions (#74) 2021-11-19 13:19:46 -05:00
go.mod Upgrade to go 1.23 (#110) 2025-01-07 11:27:24 -05:00
go.sum Upgrade to go 1.23 (#110) 2025-01-07 11:27:24 -05:00
ios.go test against supported go versions (#74) 2021-11-19 13:19:46 -05:00
keychain.go Add support for internet password items (#95) 2023-05-18 14:58:16 -04:00
LICENSE Initial commit 2015-09-24 12:41:15 -07:00
macos.go Remove deprecated function call (#99) 2023-05-22 23:03:00 -04:00
macos_test.go cleanup generic password test (#100) 2023-05-22 23:07:12 -04:00
README.md Update README.md 2025-01-23 19:18:43 -05:00
util.go clean up go.mod manifest and update tool deps (#67) 2020-11-20 20:30:09 -05:00

Go Keychain

Build Status

A library for accessing the Keychain for macOS, iOS, and Linux in Go (golang).

Requires macOS 10.9 or greater and iOS 8 or greater. On Linux, communicates to a provider of the DBUS SecretService spec like gnome-keyring or ksecretservice.

import "github.com/keybase/go-keychain"

Mac/iOS Usage

The API is meant to mirror the macOS/iOS Keychain API and is not necessarily idiomatic go.

Add Item

item := keychain.NewItem()
item.SetSecClass(keychain.SecClassGenericPassword)
item.SetService("MyService")
item.SetAccount("gabriel")
item.SetLabel("A label")
item.SetAccessGroup("A123456789.group.com.mycorp")
item.SetData([]byte("toomanysecrets"))
item.SetSynchronizable(keychain.SynchronizableNo)
item.SetAccessible(keychain.AccessibleWhenUnlocked)
err := keychain.AddItem(item)

if err == keychain.ErrorDuplicateItem {
  // Duplicate
}

Query Item

Query for multiple results, returning attributes:

query := keychain.NewItem()
query.SetSecClass(keychain.SecClassGenericPassword)
query.SetService(service)
query.SetAccount(account)
query.SetAccessGroup(accessGroup)
query.SetMatchLimit(keychain.MatchLimitAll)
query.SetReturnAttributes(true)
results, err := keychain.QueryItem(query)
if err != nil {
  // Error
} else {
  for _, r := range results {
    fmt.Printf("%#v\n", r)
  }
}

Query for a single result, returning data:

query := keychain.NewItem()
query.SetSecClass(keychain.SecClassGenericPassword)
query.SetService(service)
query.SetAccount(account)
query.SetAccessGroup(accessGroup)
query.SetMatchLimit(keychain.MatchLimitOne)
query.SetReturnData(true)
results, err := keychain.QueryItem(query)
if err != nil {
  // Error
} else if len(results) != 1 {
  // Not found
} else {
  password := string(results[0].Data)
}

Delete Item

Delete a generic password item with service and account:

item := keychain.NewItem()
item.SetSecClass(keychain.SecClassGenericPassword)
item.SetService(service)
item.SetAccount(account)
err := keychain.DeleteItem(item)

Other

There are some convenience methods for generic password:

// Create generic password item with service, account, label, password, access group
item := keychain.NewGenericPassword("MyService", "gabriel", "A label", []byte("toomanysecrets"), "A123456789.group.com.mycorp")
item.SetSynchronizable(keychain.SynchronizableNo)
item.SetAccessible(keychain.AccessibleWhenUnlocked)
err := keychain.AddItem(item)
if err == keychain.ErrorDuplicateItem {
  // Duplicate
}

password, err := keychain.GetGenericPassword("MyService", "gabriel", "A label", "A123456789.group.com.mycorp")

accounts, err := keychain.GetGenericPasswordAccounts("MyService")
// Should have 1 account == "gabriel"

err := keychain.DeleteGenericPasswordItem("MyService", "gabriel")
if err == keychain.ErrorItemNotFound {
  // Not found
}

iOS

Bindable package in bind. iOS project in ios. Run that project to test iOS.

To re-generate framework:

(cd bind && gomobile bind -target=ios -tags=ios -o ../ios/bind.framework)

Post issues to: https://github.com/keybase/keybase-issues