Lightweight Go library for sealing and unsealing data using AEAD (AES-GCM) with built-in key routing.
go get github.com/rah-0/aegis// Define a codec (or use any serialization: JSON, msgpack, protobuf, etc.)
type jsonCodec struct{}
func (jsonCodec) Encode(v any) ([]byte, error) { return json.Marshal(v) }
func (jsonCodec) Decode(data []byte, v any) error { return json.Unmarshal(data, v) }
// Create a vault
vault, err := aegis.NewVault(jsonCodec{})
if err != nil {
log.Fatal(err)
}
// Register a 32-byte key under a label
key := []byte("my-32-byte-secret-key-here!!1234")
if err := vault.AddSecret("default", key); err != nil {
log.Fatal(err)
}
// Seal
sealed, err := vault.Seal("default", map[string]string{"user": "alice"})
if err != nil {
log.Fatal(err)
}
// Unseal — label is embedded, key routing is automatic
var result map[string]string
if err := vault.Unseal(sealed, &result); err != nil {
log.Fatal(err)
}// Bulk load multiple keys
vault.LoadSecrets([]aegis.Secret{
{Label: "primary", Key: key1},
{Label: "secondary", Key: key2},
})
// Rotate a key at runtime (hot-reload)
vault.UpdateSecret("primary", newKey)
// Remove a key
vault.RemoveSecret("secondary")Implement the Codec interface to use any serialization format:
type Codec interface {
Encode(v any) ([]byte, error)
Decode(data []byte, v any) error
}- Encrypting session tokens, cookies, or API payloads
- Sealing configuration secrets or credentials at rest
- Cross-service encryption — all services that need to seal/unseal must share the same labels and keys
- Any scenario where you need authenticated encryption with key routing
- Streaming encryption — seal/unseal data as a stream instead of loading entire payloads in memory
- File encryption — chunked AEAD for large files
- Nonce-misuse resistance (AES-GCM-SIV) — Go's
x/cryptohas an accepted proposal foraesgcmsiv, currently in backlog. Once shipped, aegis will support it as an alternative AEAD backend
- Password hashing — use bcrypt/scrypt/argon2 instead
- Key exchange or asymmetric crypto — aegis is symmetric-key only
[label-len-size: 1 byte] — number of bytes used to encode label length
[label-len: 1–8 bytes] — label length as big-endian uint
[label: N bytes] — label string, length defined above
[nonce: 12 bytes] — GCM nonce (fixed)
[ciphertext: variable] — encrypted data
[auth-tag: 16 bytes] — GCM authentication tag (appended to ciphertext by AEAD)
- AES-256-GCM: 256-bit key (enforced), 12-byte random nonce, 16-byte authentication tag
- CSPRNG nonces: Generated via
crypto/rand, nonce collision probability is negligible below ~2⁴⁸ operations per key - Key material never leaves memory: Keys are stored as
cipher.AEADinterfaces, the raw bytes are not retained - Concurrent-safe: All vault operations are protected by
sync.RWMutex
See BENCHMARK.md for detailed results comparing JSON vs binary codecs across message sizes, label sizes, and full round-trips.
Key takeaways:
- Seal at ~550 MB/s (JSON) or ~960 MB/s (binary) for 64 KB payloads
- Unseal at ~200 MB/s (JSON) or ~1,450 MB/s (binary) — codec choice dominates unseal performance
- Constant allocation count (5 allocs) regardless of payload size
- Label size has negligible impact on performance
If this saved you time or brought value to your project, feel free to show some support. Every bit is appreciated 🙂
