barrel_crypto
Encryption primitives and key providers for Barrel's encryption at rest.
Provides an AES-256-GCM envelope with HKDF-SHA256 key derivation,
offset-addressable AES-256-CTR for sector-encrypted flat files, key-check
tokens for fail-closed wrong-key detection, and the barrel_keyprovider
behaviour that maps a database keyspace to its 256-bit key.
Documentation | HexDocs | Repository
Encryption is off by default. Databases opt in with an encryption spec at
open: default resolves keys through barrel_keyprovider_env
(BARREL_ENCRYPTION_KEY as 32 raw bytes, 64 hex chars, or a passphrase;
per-database keys are derived from it with the keyspace as HKDF info), and
#{provider => Mod} plugs in a custom provider (KMS, token-derived).
Use
{ok, Key} = barrel_keyprovider:key_for_db(default, <<"mydb">>),
%% GCM envelope for whole values
Enc = barrel_crypto:encrypt(<<"secret">>, Key),
true = barrel_crypto:is_encrypted(Enc),
<<"secret">> = barrel_crypto:decrypt(Enc, Key),
%% offset-addressable CTR for flat files
Nonce = barrel_crypto:new_nonce(8),
Ct = barrel_crypto:ctr_crypt(Key, Nonce, 0, <<"some file bytes">>),
<<"file">> = barrel_crypto:ctr_crypt(Key, Nonce, 5, binary:part(Ct, 5, 4)),
%% wrong-key detection without key material on disk
Token = barrel_crypto:key_check_new(Key),
true = barrel_crypto:key_check_verify(Key, Token).
barrel_crypto:decrypt/2 returns unencrypted input unchanged, so it is safe
to call on values written before encryption was enabled.
Custom provider
-module(my_kms_provider).
-behaviour(barrel_keyprovider).
-export([key_for_db/1]).
key_for_db(Keyspace) ->
{ok, my_kms:fetch_data_key(Keyspace)}. %% must be exactly 32 bytes