column_encrypt v4.0
Transparent column-level encryption for PostgreSQL - Major Simplification Release
v4.0 is a clean API release that removes all deprecated functionality from previous versions, providing a minimal, secure, and easy-to-use encryption API.
Highlights
- Simplified API: All functions consolidated under the
encryptschema - Single role model: Unified
column_encrypt_userrole replaces the 3-role system - Automatic log masking: No more manual
cipher_key_disable_log()calls - Fixed
encryptschema: Improved security with non-relocatable extension
Security Updates (v4.0.1 patch)
Log Masking Fixes
Fixed: encrypt.register_key() and encrypt.blind_index() were not being masked in PostgreSQL logs. DEK, passphrase, and HMAC key arguments could leak into server logs on validation errors.
The emit_log_hook regex now includes all sensitive functions:
register_key,load_key,blind_index- Legacy:
register_cipher_key,load_key_by_version,enc_store_key,enc_store_prv_key
INSERT/UPDATE Data Protection
New guidance: For comprehensive protection of sensitive data in INSERT/UPDATE statements, enable the encrypt.mask_query_literals GUC:
-- In postgresql.conf or per-session:
SET encrypt.mask_query_literals = on;This masks ALL string literals in logged queries, protecting:
- DEK values in INSERT/UPDATE statements
- Passphrase values passed to functions
- Any other string literal data
Trade-off: You lose visibility into actual values in logs, but gain complete protection against accidental secret exposure.
Installation
# Build and install
make && make install
# Add to postgresql.conf
shared_preload_libraries = 'column_encrypt'
# In PostgreSQL:
CREATE SCHEMA IF NOT EXISTS encrypt;
CREATE EXTENSION column_encrypt;Supported PostgreSQL versions: 14, 15, 16, 17, 18
v4.0 API Reference
| Function | Description |
|---|---|
encrypt.register_key(dek, passphrase, [activate]) |
Register new encryption key |
encrypt.load_key(passphrase, [all_versions]) |
Load key(s) into session |
encrypt.unload_key() |
Clear keys from session |
encrypt.activate_key(key_id) |
Set active key for new encryptions |
encrypt.revoke_key(key_id) |
Prevent key from being loaded |
encrypt.rotate(schema, table, column, [batch_size]) |
Re-encrypt with active key |
encrypt.verify(schema, table, column, [sample_size]) |
Verify encryption integrity |
encrypt.keys() |
List all registered keys |
encrypt.status() |
Quick status check |
encrypt.blind_index(value, hmac_key) |
Create searchable blind index |
Upgrade Path
v2.0 → v3.0 → v3.1 → v3.3 → v4.0
Important: Upgrade through v3.3 first to migrate your code from deprecated functions:
-- Step 1: Upgrade to v3.3 (deprecation release)
ALTER EXTENSION column_encrypt UPDATE TO '3.3';
-- Step 2: Update code to use encrypt.* API
-- Step 3: Upgrade to v4.0
ALTER EXTENSION column_encrypt UPDATE TO '4.0';See MIGRATION.md for the complete guide.
Complete Version History
v4.0 (This Release)
Removed (use new encrypt.* API instead):
cipher_key_disable_log()/cipher_key_enable_log()→ Automaticregister_cipher_key()→encrypt.register_key()load_key()/load_key_by_version()→encrypt.load_key()rm_key_details()→encrypt.unload_key()activate_cipher_key()→encrypt.activate_key()revoke_cipher_key()→encrypt.revoke_key()cipher_key_versions()→encrypt.keys()cipher_key_reencrypt_data*()→encrypt.rotate()cipher_verify_column_encryption()→encrypt.verify()- All metrics, audit, and rotation job functions
cipher_key_audit_log,cipher_key_failed_attempts,cipher_rotation_jobstables
Changed:
- Single
column_encrypt_userrole replaces 3-role system - All functions use
SECURITY DEFINERwithSET search_path TO pg_catalog - Dynamic pgcrypto schema lookup (works regardless of where pgcrypto is installed)
Security:
- Fixed log masking for
register_key()andblind_index()functions - Fixed privilege escalation in SECURITY DEFINER functions
SET ROLEprivilege reduction now properly honored- Schema-qualified all object references
- Added
encrypt.mask_query_literalsGUC documentation for INSERT/UPDATE protection
v3.3 (Deprecation Release)
Added:
- New
encryptschema with all v4.0 API functions - Deprecation warnings for old functions
Purpose: Bridge release allowing code migration before v4.0
v3.1 (Production Operations)
Added:
cipher_metrics()- Encryption statisticscipher_coverage_audit()- Column coverage auditcipher_start_rotation_job()- Background rotation jobscipher_key_audit_log- Audit logging table- Key expiration checking
v3.0 (Multi-Version Keys)
Added:
- Role-based access control (3-role model)
- Key lifecycle states:
pending,active,retired,revoked - Multi-version key management with
key_versioncolumn loaded_cipher_key_versions()- Session introspectioncipher_key_reencrypt_data()/cipher_key_reencrypt_data_batch()- Key rotation- Blind index helpers
- Docker-based replication test harness
- Equality and hash semantics on decrypted plaintext (breaking change)
Changed:
- Renamed
key→wrapped_keyincipher_key_table - Hash/equality operations now use decrypted values
Upgrade Note: REINDEX hash indexes on encrypted columns after upgrade
v2.0 (Two-Tier Key Model)
Added:
- KEK/DEK model: passphrase wraps data encryption key
register_cipher_key()with passphrase wrappingload_key()for session key loading- 2-byte key version header in ciphertext
- Log masking via
emit_log_hook - Secure memory zeroing with
secure_memset
Changed:
- Keys stored wrapped (encrypted) in database
- Session keys in
TopMemoryContext
v1.0 (Initial Release)
Added:
encrypted_textandencrypted_byteacustom types- Transparent encrypt/decrypt via type I/O
encrypt.enableGUC for global controlpgcryptointegration for AES encryption- Basic equality operators and hash index support
- Type casts from
bool,inet,cidr,xml,character
Security Model
- Two-tier key model: KEK (passphrase) wraps DEK (data key)
- AES-256: Via pgcrypto with iterated-salted S2K
- Session isolation: Keys per-connection, cleared on disconnect
- Log protection: Automatic masking of sensitive function calls
- Query literal masking: Optional
encrypt.mask_query_literalsfor INSERT/UPDATE protection - SECURITY DEFINER: All functions properly secured
- Binary protocol blocked: Prevents encryption bypass
Documentation
- README - Full documentation
- MIGRATION.md - Migration guide
- CHANGELOG.md - Detailed changes
License
Full Changelog: v1.0...v4.0