██╗░░░██╗░█████╗░██╗░░░██╗██╗░░░░░████████╗
██║░░░██║██╔══██╗██║░░░██║██║░░░░░╚══██╔══╝
╚██╗░██╔╝███████║██║░░░██║██║░░░░░░░░██║░░░
░╚████╔╝░██╔══██║██║░░░██║██║░░░░░░░░██║░░░
░░╚██╔╝░░██║░░██║╚██████╔╝███████╗░░░██║░░░
░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝░░░╚═╝░░░
A simple, cross-platform secret storage library for Go. Stores secrets securely using platform-native secure storage mechanisms without CGO.
- Simple API: Just
Set,Get, andDelete - Cross-platform: macOS, Windows, Linux, iOS, Android, and Browser (wasm)
- No CGO: Pure Go implementation using platform CLI tools and file-based fallbacks
- Binary-safe: Handles binary data and special characters
go get ella.to/vaultpackage main
import (
"fmt"
"log"
"ella.to/vault"
)
func main() {
service := "myapp"
key := "api-key"
secret := []byte("super-secret-value")
// Store a secret
if err := vault.Set(service, key, secret); err != nil {
log.Fatal(err)
}
// Retrieve a secret
value, err := vault.Get(service, key)
if err != nil {
if err == vault.ErrNotFound {
fmt.Println("Secret not found")
} else {
log.Fatal(err)
}
}
fmt.Printf("Secret: %s\n", value)
// Delete a secret
if err := vault.Del(service, key); err != nil {
log.Fatal(err)
}
}| Platform | Storage Mechanism | Notes |
|---|---|---|
| macOS | Keychain via security CLI |
Uses the default keychain |
| Windows | Credential Manager via cmdkey/PowerShell |
Generic credentials |
| Linux | Secret Service via secret-tool |
Falls back to encrypted files if unavailable |
| iOS | File-based in app sandbox | Uses iOS Data Protection |
| Android | File-based in app sandbox | Uses Android app sandbox security |
| WASM/Browser | IndexedDB | Base64 encoded, same-origin accessible |
Uses the security command-line tool to interact with the Keychain. No additional setup required.
Uses cmdkey and PowerShell for Windows Credential Manager access. Works on Windows 10/11.
Prefers secret-tool (from libsecret-tools package) which integrates with GNOME Keyring, KWallet, etc. If not available, falls back to file-based storage in ~/.local/share/vault-secrets/.
Uses IndexedDB for persistent storage. Security considerations:
- Data is accessible to any JavaScript on the same origin
- No hardware-backed encryption (unlike native keychains)
- Data is cleared when user clears browser data
- For sensitive credentials, consider server-side storage or Web Crypto API encryption
Install secret-tool:
# Debian/Ubuntu
sudo apt install libsecret-tools
# Fedora
sudo dnf install libsecret
# Arch Linux
sudo pacman -S libsecretUse file-based storage within the app's sandboxed storage, which provides OS-level security isolation.
go test -v ./...
# or
make testVerify the code compiles for all platforms:
make build-allmake test-linux
# or manually:
docker run --rm -v $(pwd):/app -w /app golang:latest go test -v ./...Options for testing on Windows:
- Windows VM: Use VirtualBox, Parallels, or VMware with a Windows image
- GitHub Actions: Add Windows to your CI matrix
- Azure DevOps: Use Windows build agents
Example GitHub Actions workflow:
name: Test
on: [push, pull_request]
jobs:
test:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Test
run: go test -v ./...- iOS: Use Xcode simulator or device via gomobile
- Android: Use Android emulator or device via gomobile
Stores a secret. Overwrites if it already exists.
Retrieves a secret. Returns ErrNotFound if not found.
Deletes a secret. Returns ErrNotFound if not found.
ErrNotFound: The requested key does not existErrInvalidKey: Service or key is emptyErrInvalidValue: Value is empty or nil
- macOS/Windows: Secrets are stored in platform-native secure storage with OS-level encryption
- Linux: With
secret-tool, uses the system keyring. File fallback uses base64 encoding (not encrypted) - iOS/Android: File-based storage relies on OS sandbox isolation
- Memory: Secrets are held in memory as
[]byte; consider zeroing after use for sensitive data
MIT