This document defines functional and non-functional requirements for a PostgreSQL extension that provides modern, KMS-backed column-level encryption. The implementation uses:
- A Rust cryptographic core,
- Exposed to PostgreSQL via a thin C shim,
- Allowing compatibility with PostgreSQL versions beyond what
pgxcurrently supports.
The goal is to make secure, authenticated column encryption simple and maintainable for enterprise use cases.
In-scope (overall project):
- Column-level encryption & decryption UDFs
- Envelope encryption with external KMS
- Key rotation with versioned crypto schemes
- Catalog tables for metadata
- A standalone Rust crypto engine invoked through a C shim
Out-of-scope:
- Transparent tablespace/WAL encryption
- Replacing PostgreSQL authentication or RLS
- Graphical user interfaces
- Implementing new KMS systems
- Simple adoption via SQL functions.
- Strong security posture (modern, authenticated encryption; no DIY crypto).
- Safe and secure-by-default.
- Versioned crypto schemes for long-term maintenance.
- Future-proof PostgreSQL version compatibility via C shim.
- Easy local testing using a KMS backend that runs on a laptop.
- Fully transparent TDE.
- Acting as a full enterprise DAM/DLP product.
- Full IAM/RBAC replacement.
- Zero-configuration magic encryption.
- Application developers
- DBAs and SREs
- Security & compliance teams
- Encrypting PII (email, phone numbers, SSNs) at rest
- Using Vault/KMS keys instead of in-app key management
- Rotating keys or algorithms without breaking applications
- Supporting multi-application or multi-tenant deployments
- PostgreSQL versions 13–18
- Linux (primary), other OS best-effort
- Shared library extension
- Rust library (
cdylibor staticlib): crypto, KMS integration, envelope logic - C shim: PostgreSQL-facing wrapper (SQL-callable functions)
- Build: Cargo + PGXS/CMake
HashiCorp Vault Transit Engine
Chosen because:
- Popular in enterprises
- Easy to run locally (Docker or dev mode)
- Clean encrypt/decrypt API
- Compatible with envelope encryption workflows
KMS integration is abstracted to allow AWS KMS, GCP KMS, Azure Key Vault later.
Provide SQL functions:
encrypt_column(plaintext anyelement, key_alias text) RETURNS byteadecrypt_column(ciphertext bytea) RETURNS anyelement
Requirements:
- Support baseline types:
text,varchar,bytea,int4,int8,numeric - Always use AEAD (AES-256-GCM or XChaCha20-Poly1305)
- Include AEAD AAD: table, column, optional tenant/app ID
Create schema pgenvelope (name TBD):
Tables:
pgenvelope_schemes
scheme_idnamealgorithmkms_key_aliasencrypted_dekactivecreated_at
pgenvelope_config
- KMS type (
vault) - Endpoint
- Credentials
- Global settings
-
Data Encryption Key (DEK) encrypted with KMS, stored locally
-
Ciphertexts embed:
- scheme ID
- nonce
- ciphertext
-
DEKs cached in memory with TTL to avoid KMS round-trips
- Ability to create new scheme versions
- Mark active/inactive
- Manually re-encrypt a column:
pgenvelope_reencrypt_column(table_name, column_name, target_scheme_id)
VaultKmsClientimplements traitKmsClient- Token-based auth from config
- Errors must distinguish transient vs permanent
Core SQL API:
encrypt_columndecrypt_columnpgenvelope_create_scheme(...)pgenvelope_activate_scheme(...)pgenvelope_deactivate_scheme(...)pgenvelope_show_schemes()pgenvelope_test_kms()pgenvelope_reencrypt_column(...)
Permissions:
- Only superuser or role
pgenvelope_adminmay manage config/schemes - Apps can be granted encrypt/decrypt rights
- Clear error on tag mismatch, invalid ciphertext, unknown scheme
- No logging of plaintext or keys
- Configurable logging level (MVP subset ok)
- PostgreSQL wrappers defined in C
- Rust functions exposed via stable ABI
- Memory always allocated in PostgreSQL contexts (palloc)
- ABI version check must be performed
- Rust crypto crates must be modern and maintained
- Minimal
unsafeand only at FFI boundary - Performance should not regress typical OLTP workloads excessively
- Integration tests using local Vault instance
- Documented threat model
- AWS KMS
- GCP KMS
- Azure Key Vault
- PKCS#11 / HSM
- Explicit deterministic mode for equality search
- Hash-based indexing helpers
encrypted_text,encrypted_int, etc.- Provides near-transparent I/O
- RLS-aware decrypt-or-mask functions
- Column policies defining who may decrypt what
- Background jobs
- Incremental re-encryption with progress tracking
- Resumable jobs
- Per-tenant key aliases
- Tenant-bound AEAD AAD
- Audit tables for scheme changes and reencrypt actions
- Compliance reporting views
- FIPS-mode builds
- Side-channel hardening
- Strict configuration modes
- Environment bootstrap
- Offline migration
- Configuration validation