Add temporary file encryption (encrypt_temp_files) - #2
Merged
Conversation
Encrypt query-spill temporary files (external sorts, hash joins, and other BufFile spills that exceed work_mem), closing a documented data-at-rest gap. Core patch (0002 in each version series, gated behind USE_TDE_HOOKS): a registrable hook on the temporary-file path. BufFileDumpBuffer passes each buffer through temp_file_encrypt_hook before writing, and BufFileLoadBuffer passes it through temp_file_decrypt_hook after reading, when the new encrypt_temp_files GUC is on. Core implements no cipher; with the flag off the hooks and GUC do not exist and the tree builds as clean PostgreSQL. Extension: open_pg_tde_tempfile.c installs the hooks in _PG_init and supplies AES-128-CBC per 8 kB block (IV derived from block position, partial tail masked with an AES-ECB keystream so length is preserved). The key is generated once in the postmaster and inherited by every backend through fork, so parallel workers sharing a temporary file set use the same key. Temporary files never outlive the cluster, so the key is held only in memory and never written to disk; the on-disk temporary data cannot be recovered once the server stops. Verified on PostgreSQL 16, 17, and 18: t/temp_file_encryption.pl passes (with the GUC off a canary is plaintext in pgsql_tmp; with it on the temp files are ciphertext and a 200k-row spilling sort still returns correct results). Gate off builds clean with the encrypt_temp_files symbol absent. The 0002 patch applies on top of 0001 and is pgindent-clean; the module and test are pgindent/perltidy-clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds temporary file encryption (
encrypt_temp_files), which encrypts query-spill temporary files (external sorts, hash joins, and otherBufFilespills that exceedwork_mem). This closes a documented data-at-rest gap: previously those files were written to disk in plaintext.Design
Core patch (
0002-*in each version series, gated behindUSE_TDE_HOOKS): a registrable hook on the temporary-file path.BufFileDumpBufferpasses each buffer throughtemp_file_encrypt_hookbefore writing, andBufFileLoadBufferpasses it throughtemp_file_decrypt_hookafter reading, when the newencrypt_temp_filesGUC is on. Core implements no cipher. With the flag off, the hooks and GUC do not exist and the tree builds as clean PostgreSQL.Extension (
src/open_pg_tde_tempfile.c): installs the hooks in_PG_initand supplies AES-128-CBC per 8 kB block (IV derived from block position; a partial trailing sub-block is masked with an AES-ECB keystream so ciphertext length equals plaintext length and file offsets are unchanged).Key model: the key is generated once in the postmaster and inherited by every backend through
fork, so parallel workers sharing a temporary file set use the same key. Temporary files never outlive the cluster, so the key is held only in memory and never written to disk. Once the server stops, the on-disk temporary data cannot be recovered, even with access to the storage media. This is a deliberate choice: ephemeral data does not need cross-restart decryption, so keeping zero key material on disk is a security benefit.Testing
t/temp_file_encryption.plverified on PostgreSQL 16, 17, and 18 (6 subtests each):encrypt_temp_filesoff, a canary string is present in thepgsql_tmpfiles (control).Also verified per version:
encrypt_temp_filessymbol absent from the binary.0002patch applies on top of0001and ispgindent-clean (0 residual diff). The module and test arepgindent/perltidy-clean.Usage
Docs
Updates the limitations page (temp files are now encryptable) and adds
encrypt_temp_filesto the GUC reference.🤖 Generated with Claude Code