Encryption¶
Introduction¶
Arvel's encryption services provide a simple, convenient interface for encrypting and decrypting text via AES-256-GCM. All encrypted values are authenticated, so their underlying value cannot be modified or tampered with once encrypted.
The Crypt facade is the entry point. It's also what powers the encrypted:* model casts.
Configuration¶
Before using the encrypter, set the APP_KEY environment variable. Generate one with:
This writes a base64-encoded 32-byte key to your .env as APP_KEY=base64:....
Warning
Encryption requires APP_KEY. Calling the encrypter without it raises MissingAppKeyError. Keep the key secret and out of source control — anyone with it can decrypt your data.
Using the Encrypter¶
Encrypting Strings¶
Encrypting Values¶
encrypt / decrypt handle arbitrary JSON-serializable values — they serialize to JSON, then encrypt:
token = Crypt.encrypt({"user_id": 1, "scopes": ["read", "write"]})
data = Crypt.decrypt(token) # back to the dict
How It Works¶
The Encrypter uses AES-256-GCM from the cryptography library. The 32-byte key is derived from your APP_KEY with HKDF-SHA256. Each encryption produces a self-describing payload — a version byte, a random 12-byte IV, and the authenticated ciphertext — base64-encoded for transport. Decryption verifies the version and authentication tag, raising DecryptionError on any tampering or version mismatch.
Note
The application encrypter (Crypt, used by encrypted:* casts) and the column-level EncryptedType decorator use different wire formats. They are not interchangeable: data encrypted with one can't be read by the other. Use Crypt / encrypted:* casts for app-key-backed encryption, and EncryptedType only when you manage the raw key yourself.
Generating & Rotating Keys¶
arvel key:generate # write a new APP_KEY to .env
arvel key:generate --show # print a key without writing it
arvel key:generate --force # overwrite an existing key
Warning
arvel key:rotate is not implemented — it currently exits with a "not implemented" message. Rotating the application key by hand will make all existing ciphertext (encrypted columns, signed values) unreadable, so plan key changes carefully and re-encrypt data as part of the rotation.