go-certstore
Access X.509 certificate identities and their private-key signers from Go. Use native operating-system stores, PKCS#11 tokens, or NSS databases through one focused API.
The library returns a crypto.Signer. Signing happens in Keychain, the Windows Certificate Store, a token, HSM, or NSS database.
Installation#
Add the latest release to your module:
go get github.com/sukujgrg/go-certstore@latestQuick start#
Open the default backend for the current platform and list its identities:
package main
import (
"context"
"fmt"
certstore "github.com/sukujgrg/go-certstore"
)
func main() {
ctx := context.Background()
store, err := certstore.Open(ctx)
if err != nil {
panic(err)
}
defer store.Close()
identities, err := store.Identities(ctx)
if err != nil {
panic(err)
}
fmt.Printf("found %d identities\n", len(identities))
}Linux has no native backend. Select BackendPKCS11 or BackendNSS explicitly.
Platform support#
| Backend | Host OS | Status | cgo |
|---|---|---|---|
| KeychainSecurity.framework | macOS | Supported | Yes |
| Certificate StoreCNG or CryptoAPI | Windows | Supported | Yes |
| Native system store | Linux | Unavailable | No |
| PKCS#11Explicit module path | macOS, Windows, Linux | Supported | Yes |
| NSSExplicit module + profile | macOS, Windows, Linux | Supported | Yes |
Configure a backend#
Native stores require no backend options. PKCS#11 and NSS remain explicit so your application controls module discovery, profiles, tokens, and credentials.
Native stores
Uses macOS Keychain or the Windows Certificate Store for the current user.
store, err := certstore.Open(ctx)
if err != nil {
return err
}
defer store.Close()PKCS#11
Use an explicit module for YubiKey PIV, OpenSC smart cards, HSMs, or SoftHSM.
store, err := certstore.Open(ctx,
certstore.WithBackend(certstore.BackendPKCS11),
certstore.WithPKCS11Module(modulePath),
certstore.WithPKCS11TokenLabel("YubiKey PIV"),
certstore.WithCredentialPrompt(prompt),
)NSS
Supply the softokn3 module and an NSS profile or database directory.
store, err := certstore.Open(ctx,
certstore.WithBackend(certstore.BackendNSS),
certstore.WithNSSModule(modulePath),
certstore.WithNSSProfileDir(profileDir),
certstore.WithCredentialPrompt(prompt),
)TLS client certificates#
For long-lived clients, open the store once and use NewClientCertificateSource. It caches compatible certificates and keeps signers alive for concurrent handshakes.
source := certstore.NewClientCertificateSource(ctx, store,
certstore.SelectOptions{
SubjectCN: "client.example.com",
RequireClientAuthEKU: true,
},
)
defer source.Close()
tlsConfig := &tls.Config{
GetClientCertificate: source.GetClientCertificate,
}Close the source before the store. Close signers obtained directly with certstore.CloseSigner.
Identity selection#
Single-result helpers rank matches. The current score prefers hardware-backed identities when requested, then currently valid certificates, then later expiration dates.
- Set
RequireCurrentlyValidto reject expired or not-yet-valid certificates. - Use
FindIdentitiesorFilterIdentitieswhen you need every match. ClientCertificateSourcealways requires a currently valid certificate.
Credentials & resource lifetime#
WithCredentialPrompt gives credential collection to the application. The callback returns []byte, and the library clears that buffer after use.
Return a dedicated buffer. The cgo runtime or a dependency can make an internal copy, so this is not a high-assurance secret-memory system.
Runnable examples#
The repository includes complete programs. They inspect local state and do not connect to a remote server.