sys/crypto encrypts and decrypts strings with AES-256-GCM, for example to encrypt
stored credentials. It supports key rotation: older keys can
still decrypt while new data is encrypted with the primary key.
- Module
go.getarcane.app/sys/crypto- Reference
- pkg.go.dev
go get go.getarcane.app/sys/crypto@latestEncrypting
Section titled “Encrypting”import "go.getarcane.app/sys/crypto"
key, err := crypto.ParseKey(os.Getenv("ENCRYPTION_KEY"))if err != nil { return err}
enc, err := crypto.New(key)if err != nil { return err}
ciphertext, err := enc.Encrypt("hunter2") // base64 AES-GCMplaintext, err := enc.Decrypt(ciphertext)Encrypt("")returns"", so empty, nullable fields stay empty.- Each call uses a fresh random 96-bit nonce. Don’t encrypt more than 2³² messages with one key.
Key material
Section titled “Key material”ParseKey accepts:
| Input | Interpreted as |
|---|---|
hex:… |
A hex-encoded 32-byte key |
base64:… |
A base64-encoded 32-byte key |
| anything else | A passphrase, turned into a key with HKDF-SHA256 |
Requiring a prefix means a passphrase that happens to look like hex is never mistaken for a raw key.
Other key helpers:
key, err := crypto.GenerateKey() // random 32-byte keyerr = crypto.SaveKeyFile("/data/.key", key) // hex, atomic, mode 0600key, err = crypto.LoadKeyFile("/data/.key")Rotating keys
Section titled “Rotating keys”Pass the old keys after the primary key. Decryption tries the primary key first, then each old key in order:
enc, err := crypto.New(newKey, oldKey1, oldKey2)
plain, err := enc.Decrypt(storedValue) // works for values written with any of the keysfresh, err := enc.Encrypt(plain) // always written with newKeyPackage-level encryptor
Section titled “Package-level encryptor”InitEncryption, Encrypt, Decrypt, and Default use a process-wide encryptor for code that
doesn’t yet pass an *Encryptor around. Prefer constructing one with New and passing it
explicitly.
Errors
Section titled “Errors”| Type | Meaning |
|---|---|
*InvalidKeyError |
The key material is malformed or the wrong size |
*CiphertextError |
The ciphertext is structurally invalid |
*DecodeError |
The ciphertext is not valid base64 |
*DecryptError |
Authentication failed: wrong key or tampered data |
*RandomError |
The system’s random source failed |