Transparent Column Encryption (TCE) uses PostgreSQL triggers to automatically encrypt columns in a table and decrypt them via a view. This is enabled using the SECURITY LABEL command. TCE requires keys created via the Key Management API (specifically of type aead-det).
Pattern 1: One Key ID for the Entire Column
Simple approach where one key encrypts all rows in a column. Uses the nonceless crypto_aead_det_xchacha20() algorithm.
CREATE TABLE private.users (id bigserial primary key, secret text);
SECURITY LABEL FOR pgsodium ON COLUMN private.users.secret IS 'ENCRYPT WITH KEY ID <UUID>';
Pattern 2: One Key ID per Row
More secure approach where each row has its own key and nonce. This prevents a single key compromise from exposing the entire column and allows for easier key rotation.
CREATE TABLE private.users (id bigserial primary key, secret text, key_id uuid not null, nonce bytea);
SECURITY LABEL FOR pgsodium ON COLUMN private.users.secret IS 'ENCRYPT WITH KEY COLUMN key_id';
Pattern 3: One Key ID per Row with Nonce and Associated Data
Provides the highest security by using a unique nonce and mixing additional metadata (associated data) into the authentication signature to ensure the plaintext hasn't been altered.
CREATE TABLE private.users (id bigserial primary key, secret text, key_id uuid not null, nonce bytea, associated_data text);
SECURITY LABEL FOR pgsodium ON COLUMN private.users.secret IS 'ENCRYPT WITH KEY COLUMN key_id NONCE nonce ASSOCIATED (id, associated_data)';
Note: Columns used for associated data must be deterministically castable to text.
-- Example: One Key ID per Row with Nonce and Associated Data
CREATE TABLE private.users (
id bigserial primary key,
secret text,
key_id uuid not null,
nonce bytea,
associated_data text
);
SECURITY LABEL FOR pgsodium
ON COLUMN private.users.secret
IS 'ENCRYPT WITH KEY COLUMN key_id NONCE nonce ASSOCIATED (id, associated_data)';